~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kchart/kdchart/src/KDChartAbstractDiagram.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
 
/****************************************************************************
2
 
 ** Copyright (C) 2007 Klaralvdalens Datakonsult AB.  All rights reserved.
3
 
 **
4
 
 ** This file is part of the KD Chart library.
5
 
 **
6
 
 ** This file may be used under the terms of the GNU General Public
7
 
 ** License versions 2.0 or 3.0 as published by the Free Software
8
 
 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
9
 
 ** included in the packaging of this file.  Alternatively you may (at
10
 
 ** your option) use any later version of the GNU General Public
11
 
 ** License if such license has been publicly approved by
12
 
 ** Klarälvdalens Datakonsult AB (or its successors, if any).
13
 
 ** 
14
 
 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
15
 
 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
16
 
 ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
17
 
 ** not expressly granted herein.
18
 
 ** 
19
 
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20
 
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21
 
 **
22
 
 **********************************************************************/
23
 
 
24
 
#include "KDChartAbstractDiagram.h"
25
 
#include "KDChartAbstractDiagram_p.h"
26
 
 
27
 
#include <QPainter>
28
 
#include <QDebug>
29
 
#include <QApplication>
30
 
#include <QAbstractProxyModel>
31
 
#include <QAbstractTextDocumentLayout>
32
 
#include <QStandardItemModel>
33
 
#include <QSizeF>
34
 
#include <QTextDocument>
35
 
 
36
 
#include "KDChartAbstractCoordinatePlane.h"
37
 
#include "KDChartChart.h"
38
 
#include "KDChartDataValueAttributes.h"
39
 
#include "KDChartTextAttributes.h"
40
 
#include "KDChartMarkerAttributes.h"
41
 
#include "KDChartAbstractThreeDAttributes.h"
42
 
#include "KDChartThreeDLineAttributes.h"
43
 
 
44
 
#include <KDABLibFakes>
45
 
 
46
 
#define PI 3.141592653589793
47
 
 
48
 
using namespace KDChart;
49
 
 
50
 
AbstractDiagram::Private::Private()
51
 
  : plane( 0 )
52
 
  , attributesModel( new PrivateAttributesModel(0,0) )
53
 
  , allowOverlappingDataValueTexts( false )
54
 
  , antiAliasing( true )
55
 
  , percent( false )
56
 
  , datasetDimension( 1 )
57
 
  , databoundariesDirty(true)
58
 
  , lastRoundedValue()
59
 
  , lastX( 0 )
60
 
  , mCachedFontMetrics( QFontMetrics( qApp->font() ) )
61
 
{
62
 
}
63
 
 
64
 
AbstractDiagram::Private::~Private()
65
 
{
66
 
  if( attributesModel && qobject_cast<PrivateAttributesModel*>(attributesModel) )
67
 
    delete attributesModel;
68
 
}
69
 
 
70
 
void AbstractDiagram::Private::init()
71
 
{
72
 
}
73
 
 
74
 
void AbstractDiagram::Private::init( AbstractCoordinatePlane* newPlane )
75
 
{
76
 
    plane = newPlane;
77
 
}
78
 
 
79
 
bool AbstractDiagram::Private::usesExternalAttributesModel()const
80
 
{
81
 
    return ( ! attributesModel.isNull() ) &&
82
 
           ( ! qobject_cast<PrivateAttributesModel*>(attributesModel) );
83
 
}
84
 
 
85
 
void AbstractDiagram::Private::setAttributesModel( AttributesModel* amodel )
86
 
{
87
 
    if( !attributesModel.isNull() &&
88
 
        qobject_cast<PrivateAttributesModel*>(attributesModel) ) {
89
 
        delete attributesModel;
90
 
    }
91
 
    attributesModel = amodel;
92
 
}
93
 
 
94
 
AbstractDiagram::Private::Private( const AbstractDiagram::Private& rhs ) :
95
 
    // Do not copy the plane
96
 
    plane( 0 ),
97
 
    attributesModelRootIndex( QModelIndex() ),
98
 
    attributesModel( rhs.attributesModel ),
99
 
    allowOverlappingDataValueTexts( rhs.allowOverlappingDataValueTexts ),
100
 
    antiAliasing( rhs.antiAliasing ),
101
 
    percent( rhs.percent ),
102
 
    datasetDimension( rhs.datasetDimension ),
103
 
    mCachedFontMetrics( rhs.cachedFontMetrics() )
104
 
{
105
 
    attributesModel = new PrivateAttributesModel( 0, 0);
106
 
    attributesModel->initFrom( rhs.attributesModel );
107
 
}
108
 
 
109
 
#define d d_func()
110
 
 
111
 
AbstractDiagram::AbstractDiagram ( QWidget* parent, AbstractCoordinatePlane* plane )
112
 
    : QAbstractItemView ( parent ), _d( new Private() )
113
 
{
114
 
    _d->init( plane );
115
 
    init();
116
 
}
117
 
 
118
 
AbstractDiagram::~AbstractDiagram()
119
 
{
120
 
    delete _d;
121
 
}
122
 
 
123
 
void AbstractDiagram::init()
124
 
{
125
 
    d->reverseMapper.setDiagram( this );
126
 
}
127
 
 
128
 
 
129
 
bool AbstractDiagram::compare( const AbstractDiagram* other )const
130
 
{
131
 
    if( other == this ) return true;
132
 
    if( ! other ){
133
 
        //qDebug() << "AbstractDiagram::compare() cannot compare to Null pointer";
134
 
        return false;
135
 
    }
136
 
    /*
137
 
    qDebug() << "\n             AbstractDiagram::compare() QAbstractScrollArea:";
138
 
            // compare QAbstractScrollArea properties
139
 
    qDebug() <<
140
 
            ((horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
141
 
            (verticalScrollBarPolicy()    == other->verticalScrollBarPolicy()));
142
 
    qDebug() << "AbstractDiagram::compare() QFrame:";
143
 
            // compare QFrame properties
144
 
    qDebug() <<
145
 
            ((frameShadow() == other->frameShadow()) &&
146
 
            (frameShape()   == other->frameShape()) &&
147
 
            (frameWidth()   == other->frameWidth()) &&
148
 
            (lineWidth()    == other->lineWidth()) &&
149
 
            (midLineWidth() == other->midLineWidth()));
150
 
    qDebug() << "AbstractDiagram::compare() QAbstractItemView:";
151
 
            // compare QAbstractItemView properties
152
 
    qDebug() <<
153
 
            ((alternatingRowColors() == other->alternatingRowColors()) &&
154
 
            (hasAutoScroll()         == other->hasAutoScroll()) &&
155
 
#if QT_VERSION > 0x040199
156
 
            (dragDropMode()          == other->dragDropMode()) &&
157
 
            (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
158
 
            (horizontalScrollMode()  == other->horizontalScrollMode ()) &&
159
 
            (verticalScrollMode()    == other->verticalScrollMode()) &&
160
 
#endif
161
 
            (dragEnabled()           == other->dragEnabled()) &&
162
 
            (editTriggers()          == other->editTriggers()) &&
163
 
            (iconSize()              == other->iconSize()) &&
164
 
            (selectionBehavior()     == other->selectionBehavior()) &&
165
 
            (selectionMode()         == other->selectionMode()) &&
166
 
            (showDropIndicator()     == other->showDropIndicator()) &&
167
 
            (tabKeyNavigation()      == other->tabKeyNavigation()) &&
168
 
            (textElideMode()         == other->textElideMode()));
169
 
    qDebug() << "AbstractDiagram::compare() AttributesModel: ";
170
 
            // compare all of the properties stored in the attributes model
171
 
    qDebug() << attributesModel()->compare( other->attributesModel() );
172
 
    qDebug() << "AbstractDiagram::compare() own:";
173
 
            // compare own properties
174
 
    qDebug() <<
175
 
            ((rootIndex().column()            == other->rootIndex().column()) &&
176
 
            (rootIndex().row()                == other->rootIndex().row()) &&
177
 
            (allowOverlappingDataValueTexts() == other->allowOverlappingDataValueTexts()) &&
178
 
            (antiAliasing()                   == other->antiAliasing()) &&
179
 
            (percentMode()                    == other->percentMode()) &&
180
 
            (datasetDimension()               == other->datasetDimension()));
181
 
    */
182
 
    return  // compare QAbstractScrollArea properties
183
 
            (horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
184
 
            (verticalScrollBarPolicy()   == other->verticalScrollBarPolicy()) &&
185
 
            // compare QFrame properties
186
 
            (frameShadow()  == other->frameShadow()) &&
187
 
            (frameShape()   == other->frameShape()) &&
188
 
// frameWidth is a read-only property defined by the style, it should not be in here:
189
 
            // (frameWidth()   == other->frameWidth()) &&
190
 
            (lineWidth()    == other->lineWidth()) &&
191
 
            (midLineWidth() == other->midLineWidth()) &&
192
 
            // compare QAbstractItemView properties
193
 
            (alternatingRowColors()  == other->alternatingRowColors()) &&
194
 
            (hasAutoScroll()         == other->hasAutoScroll()) &&
195
 
#if QT_VERSION > 0x040199
196
 
            (dragDropMode()          == other->dragDropMode()) &&
197
 
            (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
198
 
            (horizontalScrollMode()  == other->horizontalScrollMode ()) &&
199
 
            (verticalScrollMode()    == other->verticalScrollMode()) &&
200
 
#endif
201
 
            (dragEnabled()           == other->dragEnabled()) &&
202
 
            (editTriggers()          == other->editTriggers()) &&
203
 
            (iconSize()              == other->iconSize()) &&
204
 
            (selectionBehavior()     == other->selectionBehavior()) &&
205
 
            (selectionMode()         == other->selectionMode()) &&
206
 
            (showDropIndicator()     == other->showDropIndicator()) &&
207
 
            (tabKeyNavigation()      == other->tabKeyNavigation()) &&
208
 
            (textElideMode()         == other->textElideMode()) &&
209
 
            // compare all of the properties stored in the attributes model
210
 
            attributesModel()->compare( other->attributesModel() ) &&
211
 
            // compare own properties
212
 
            (rootIndex().column()             == other->rootIndex().column()) &&
213
 
            (rootIndex().row()                == other->rootIndex().row()) &&
214
 
            (allowOverlappingDataValueTexts() == other->allowOverlappingDataValueTexts()) &&
215
 
            (antiAliasing()                   == other->antiAliasing()) &&
216
 
            (percentMode()                    == other->percentMode()) &&
217
 
            (datasetDimension()               == other->datasetDimension());
218
 
}
219
 
 
220
 
AbstractCoordinatePlane* AbstractDiagram::coordinatePlane() const
221
 
{
222
 
    return d->plane;
223
 
}
224
 
 
225
 
const QPair<QPointF, QPointF> AbstractDiagram::dataBoundaries () const
226
 
{
227
 
    if( d->databoundariesDirty ){
228
 
        d->databoundaries = calculateDataBoundaries ();
229
 
        d->databoundariesDirty = false;
230
 
    }
231
 
    return d->databoundaries;
232
 
}
233
 
 
234
 
void AbstractDiagram::setDataBoundariesDirty() const
235
 
{
236
 
    d->databoundariesDirty = true;
237
 
}
238
 
 
239
 
void AbstractDiagram::setModel( QAbstractItemModel * newModel )
240
 
{
241
 
    if( model() )
242
 
    {
243
 
        disconnect( model(), SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
244
 
        disconnect( model(), SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
245
 
        disconnect( model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
246
 
        disconnect( model(), SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
247
 
        disconnect( model(), SIGNAL( modelReset() ), this, SLOT( setDataBoundariesDirty() ) );
248
 
        disconnect( model(), SIGNAL( layoutChanged() ), this, SLOT( setDataBoundariesDirty() ) );
249
 
    }
250
 
    QAbstractItemView::setModel( newModel );
251
 
    AttributesModel* amodel = new PrivateAttributesModel( newModel, this );
252
 
    amodel->initFrom( d->attributesModel );
253
 
    d->setAttributesModel(amodel);
254
 
    scheduleDelayedItemsLayout();
255
 
    setDataBoundariesDirty();
256
 
    if( model() )
257
 
    {
258
 
        connect( model(), SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
259
 
        connect( model(), SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
260
 
        connect( model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
261
 
        connect( model(), SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( setDataBoundariesDirty() ) );
262
 
        connect( model(), SIGNAL( modelReset() ), this, SLOT( setDataBoundariesDirty() ) );
263
 
        connect( model(), SIGNAL( layoutChanged() ), this, SLOT( setDataBoundariesDirty() ) );
264
 
    }
265
 
    emit modelsChanged();
266
 
}
267
 
        
268
 
void AbstractDiagram::setSelectionModel( QItemSelectionModel* newSelectionModel )
269
 
{
270
 
    if( selectionModel() )
271
 
    {
272
 
        disconnect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SIGNAL( modelsChanged() ) );
273
 
        disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SIGNAL( modelsChanged() ) );
274
 
    }
275
 
    QAbstractItemView::setSelectionModel( newSelectionModel );
276
 
    if( selectionModel() )
277
 
    {
278
 
        connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SIGNAL( modelsChanged() ) );
279
 
        connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SIGNAL( modelsChanged() ) );
280
 
    }
281
 
    emit modelsChanged();
282
 
}
283
 
 
284
 
/*! Sets an external AttributesModel on this diagram. By default, a diagram has it's
285
 
  own internal set of attributes, but an external one can be set. This can be used to
286
 
  share attributes between several diagrams. The diagram does not take ownership of the
287
 
  attributesmodel.
288
 
*/
289
 
void AbstractDiagram::setAttributesModel( AttributesModel* amodel )
290
 
{
291
 
    if( amodel->sourceModel() != model() ) {
292
 
        qWarning("KDChart::AbstractDiagram::setAttributesModel() failed: "
293
 
                 "Trying to set an attributesmodel which works on a different "
294
 
                 "model than the diagram.");
295
 
        return;
296
 
    }
297
 
    if( qobject_cast<PrivateAttributesModel*>(amodel) ) {
298
 
        qWarning("KDChart::AbstractDiagram::setAttributesModel() failed: "
299
 
                 "Trying to set an attributesmodel that is private to another diagram.");
300
 
        return;
301
 
    }
302
 
    d->setAttributesModel(amodel);
303
 
    scheduleDelayedItemsLayout();
304
 
    setDataBoundariesDirty();
305
 
    emit modelsChanged();
306
 
}
307
 
 
308
 
bool AbstractDiagram::usesExternalAttributesModel()const
309
 
{
310
 
    return d->usesExternalAttributesModel();
311
 
}
312
 
 
313
 
/*! \returns a pointer to the AttributesModel currently used by this diagram. */
314
 
AttributesModel* AbstractDiagram::attributesModel() const
315
 
{
316
 
    return d->attributesModel;
317
 
}
318
 
 
319
 
QModelIndex AbstractDiagram::conditionallyMapFromSource( const QModelIndex & index ) const
320
 
{
321
 
    Q_ASSERT( !index.isValid() || index.model() == attributesModel() || index.model() == attributesModel()->sourceModel() );
322
 
    return index.model() == attributesModel()
323
 
            ? index
324
 
            : attributesModel()->mapFromSource( index );
325
 
}
326
 
 
327
 
/*! \reimpl */
328
 
void AbstractDiagram::setRootIndex ( const QModelIndex& idx )
329
 
{
330
 
    QAbstractItemView::setRootIndex(idx);
331
 
    setAttributesModelRootIndex( d->attributesModel->mapFromSource(idx) );
332
 
}
333
 
 
334
 
/*! \internal */
335
 
void AbstractDiagram::setAttributesModelRootIndex( const QModelIndex& idx )
336
 
{
337
 
    d->attributesModelRootIndex=idx;
338
 
    setDataBoundariesDirty();
339
 
    scheduleDelayedItemsLayout();
340
 
}
341
 
 
342
 
/*! returns a QModelIndex pointing into the AttributesModel that corresponds to the
343
 
  root index of the diagram. */
344
 
QModelIndex AbstractDiagram::attributesModelRootIndex() const
345
 
{
346
 
    if ( !d->attributesModelRootIndex.isValid() )
347
 
        d->attributesModelRootIndex = d->attributesModel->mapFromSource( rootIndex() );
348
 
    return d->attributesModelRootIndex;
349
 
}
350
 
 
351
 
void AbstractDiagram::setCoordinatePlane( AbstractCoordinatePlane* parent )
352
 
{
353
 
    d->plane = parent;
354
 
}
355
 
 
356
 
void AbstractDiagram::doItemsLayout()
357
 
{
358
 
    if ( d->plane ) {
359
 
        d->plane->layoutDiagrams();
360
 
        update();
361
 
    }
362
 
    QAbstractItemView::doItemsLayout();
363
 
}
364
 
 
365
 
void AbstractDiagram::dataChanged( const QModelIndex &topLeft,
366
 
                                   const QModelIndex &bottomRight )
367
 
{
368
 
    Q_UNUSED( topLeft );
369
 
    Q_UNUSED( bottomRight );
370
 
    // We are still too dumb to do intelligent updates...
371
 
    setDataBoundariesDirty();
372
 
    scheduleDelayedItemsLayout();
373
 
}
374
 
 
375
 
 
376
 
void AbstractDiagram::setHidden( const QModelIndex & index, bool hidden )
377
 
{
378
 
    d->attributesModel->setData(
379
 
        conditionallyMapFromSource( index ),
380
 
        qVariantFromValue( hidden ),
381
 
        DataHiddenRole );
382
 
    emit dataHidden();
383
 
}
384
 
 
385
 
void AbstractDiagram::setHidden( int dataset, bool hidden )
386
 
{
387
 
    // To store the flag for a dataset, we use the first column
388
 
    // that's associated with it. (i.e., with a dataset dimension
389
 
    // of two, the column of the keys)
390
 
    const int column = dataset * datasetDimension();
391
 
    d->attributesModel->setHeaderData(
392
 
        column, Qt::Vertical,
393
 
        qVariantFromValue( hidden ),
394
 
        DataHiddenRole );
395
 
    emit dataHidden();
396
 
}
397
 
 
398
 
void AbstractDiagram::setHidden( bool hidden )
399
 
{
400
 
    d->attributesModel->setModelData(
401
 
        qVariantFromValue( hidden ),
402
 
        DataHiddenRole );
403
 
    emit dataHidden();
404
 
}
405
 
 
406
 
bool AbstractDiagram::isHidden() const
407
 
{
408
 
    return qVariantValue<bool>(
409
 
        attributesModel()->modelData( DataHiddenRole ) );
410
 
}
411
 
 
412
 
bool AbstractDiagram::isHidden( int dataset ) const
413
 
{
414
 
    // To store the flag for a dataset, we use the first column
415
 
    // that's associated with it. (i.e., with a dataset dimension
416
 
    // of two, the column of the keys)
417
 
    const int column = dataset * datasetDimension();
418
 
    const QVariant boolFlag(
419
 
            attributesModel()->headerData( column, Qt::Vertical,
420
 
                    DataHiddenRole ) );
421
 
    if( boolFlag.isValid() )
422
 
        return qVariantValue< bool >( boolFlag );
423
 
    return isHidden();
424
 
}
425
 
 
426
 
bool AbstractDiagram::isHidden( const QModelIndex & index ) const
427
 
{
428
 
    return qVariantValue<bool>(
429
 
        attributesModel()->data(
430
 
            conditionallyMapFromSource(index),
431
 
            DataHiddenRole ) );
432
 
}
433
 
 
434
 
 
435
 
void AbstractDiagram::setDataValueAttributes( const QModelIndex & index,
436
 
                                              const DataValueAttributes & a )
437
 
{
438
 
    d->attributesModel->setData(
439
 
        conditionallyMapFromSource( index ),
440
 
        qVariantFromValue( a ),
441
 
        DataValueLabelAttributesRole );
442
 
    emit propertiesChanged();
443
 
}
444
 
 
445
 
 
446
 
void AbstractDiagram::setDataValueAttributes( int dataset, const DataValueAttributes & a )
447
 
{
448
 
    // To store the attributes for a dataset, we use the first column
449
 
    // that's associated with it. (i.e., with a dataset dimension
450
 
    // of two, the column of the keys)
451
 
    const int column = dataset * datasetDimension();
452
 
    d->attributesModel->setHeaderData(
453
 
        column, Qt::Vertical,
454
 
        qVariantFromValue( a ), DataValueLabelAttributesRole );
455
 
    emit propertiesChanged();
456
 
}
457
 
 
458
 
DataValueAttributes AbstractDiagram::dataValueAttributes() const
459
 
{
460
 
    return qVariantValue<DataValueAttributes>(
461
 
        attributesModel()->modelData( KDChart::DataValueLabelAttributesRole ) );
462
 
}
463
 
 
464
 
DataValueAttributes AbstractDiagram::dataValueAttributes( int dataset ) const
465
 
{
466
 
    /*
467
 
    The following did not work!
468
 
    (khz, 2008-01-25)
469
 
    If there was some attrs specified for the 0-th cells of a dataset,
470
 
    then this logic would return the cell's settings instead of the header settings:
471
 
 
472
 
    return qVariantValue<DataValueAttributes>(
473
 
        attributesModel()->data( attributesModel()->mapFromSource(columnToIndex( column )),
474
 
        KDChart::DataValueLabelAttributesRole ) );
475
 
    */
476
 
    
477
 
    // To store the attributes for a dataset, we use the first column
478
 
    // that's associated with it. (i.e., with a dataset dimension
479
 
    // of two, the column of the keys)
480
 
    const int column = dataset * datasetDimension();
481
 
 
482
 
    const QVariant headerAttrs(
483
 
            attributesModel()->headerData( column, Qt::Horizontal,
484
 
                KDChart::DataValueLabelAttributesRole ) );
485
 
    if( headerAttrs.isValid() )
486
 
        return qVariantValue< DataValueAttributes >( headerAttrs );
487
 
    return dataValueAttributes();
488
 
}
489
 
 
490
 
DataValueAttributes AbstractDiagram::dataValueAttributes( const QModelIndex & index ) const
491
 
{
492
 
    return qVariantValue<DataValueAttributes>(
493
 
        attributesModel()->data(
494
 
            conditionallyMapFromSource( index ),
495
 
            KDChart::DataValueLabelAttributesRole ) );
496
 
}
497
 
 
498
 
void AbstractDiagram::setDataValueAttributes( const DataValueAttributes & a )
499
 
{
500
 
    d->attributesModel->setModelData( qVariantFromValue( a ), DataValueLabelAttributesRole );
501
 
    emit propertiesChanged();
502
 
}
503
 
 
504
 
void AbstractDiagram::setAllowOverlappingDataValueTexts( bool allow )
505
 
{
506
 
    d->allowOverlappingDataValueTexts = allow;
507
 
    emit propertiesChanged();
508
 
}
509
 
 
510
 
bool AbstractDiagram::allowOverlappingDataValueTexts() const
511
 
{
512
 
    return d->allowOverlappingDataValueTexts;
513
 
}
514
 
 
515
 
void AbstractDiagram::setAntiAliasing( bool enabled )
516
 
{
517
 
    d->antiAliasing = enabled;
518
 
    emit propertiesChanged();
519
 
}
520
 
 
521
 
bool AbstractDiagram::antiAliasing() const
522
 
{
523
 
    return d->antiAliasing;
524
 
}
525
 
 
526
 
void AbstractDiagram::setPercentMode ( bool percent )
527
 
{
528
 
    d->percent = percent;
529
 
    emit propertiesChanged();
530
 
}
531
 
 
532
 
bool AbstractDiagram::percentMode() const
533
 
{
534
 
    return d->percent;
535
 
}
536
 
 
537
 
 
538
 
void AbstractDiagram::paintDataValueText( QPainter* painter,
539
 
                                          const QModelIndex& index,
540
 
                                          const QPointF& pos,
541
 
                                          double value )
542
 
{
543
 
    d->paintDataValueText( this, painter, index, pos, value );
544
 
}
545
 
 
546
 
 
547
 
QString AbstractDiagram::roundValues( double value,
548
 
                                      const int decimalPos,
549
 
                                      const int decimalDigits ) const
550
 
{
551
 
    return d->roundValues( value, decimalPos, decimalDigits );
552
 
}
553
 
 
554
 
void AbstractDiagram::paintDataValueTexts( QPainter* painter )
555
 
{
556
 
    if ( !checkInvariants() ) return;
557
 
    const int rowCount = model()->rowCount(rootIndex());
558
 
    const int columnCount = model()->columnCount(rootIndex());
559
 
    d->clearListOfAlreadyDrawnDataValueTexts();
560
 
    for ( int i=datasetDimension()-1; i<columnCount; i += datasetDimension() ) {
561
 
       for ( int j=0; j< rowCount; ++j ) {
562
 
           const QModelIndex index = model()->index( j, i, rootIndex() );
563
 
           double value = model()->data( index ).toDouble();
564
 
           const QPointF pos = coordinatePlane()->translate( QPointF( j, value ) );
565
 
           paintDataValueText( painter, index, pos, value );
566
 
       }
567
 
    }
568
 
}
569
 
 
570
 
 
571
 
void AbstractDiagram::paintMarker( QPainter* painter,
572
 
                                   const DataValueAttributes& a,
573
 
                                   const QModelIndex& index,
574
 
                                   const QPointF& pos )
575
 
{
576
 
    if ( !checkInvariants() || !a.isVisible() ) return;
577
 
    const MarkerAttributes ma = a.markerAttributes();
578
 
    if ( !ma.isVisible() ) return;
579
 
 
580
 
    const PainterSaver painterSaver( painter );
581
 
    // the size of the marker - unscaled
582
 
    const QSizeF maSize( ma.markerSize().width() / painter->matrix().m11(), 
583
 
                         ma.markerSize().height() / painter->matrix().m22() );
584
 
    QBrush indexBrush( brush( index ) );
585
 
    QPen indexPen( ma.pen() );
586
 
    if ( ma.markerColor().isValid() )
587
 
        indexBrush.setColor( ma.markerColor() );
588
 
 
589
 
    paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
590
 
 
591
 
    // workaround: BC cannot be changed, otherwise we would pass the
592
 
    // index down to next-lower paintMarker function. So far, we
593
 
    // basically save a circle of radius maSize at pos in the
594
 
    // reverseMapper. This means that ^^^ this version of paintMarker
595
 
    // needs to be called to reverse-map the marker.
596
 
    d->reverseMapper.addCircle( index.row(), index.column(), pos, 2 * maSize );
597
 
}
598
 
 
599
 
void AbstractDiagram::paintMarker( QPainter* painter,
600
 
                                   const QModelIndex& index,
601
 
                                   const QPointF& pos )
602
 
{
603
 
    if ( !checkInvariants() ) return;
604
 
    paintMarker( painter, dataValueAttributes( index ), index, pos );
605
 
}
606
 
 
607
 
void AbstractDiagram::paintMarker( QPainter* painter,
608
 
                                   const MarkerAttributes& markerAttributes,
609
 
                                   const QBrush& brush,
610
 
                                   const QPen& pen,
611
 
                                   const QPointF& pos,
612
 
                                   const QSizeF& maSize )
613
 
{
614
 
    const QPen oldPen( painter->pen() );
615
 
    // Pen is used to paint 4Pixels - 1 Pixel - Ring and FastCross types.
616
 
    // make sure to use the brush color - see above in those cases.
617
 
    const bool isFourPixels = (markerAttributes.markerStyle() == MarkerAttributes::Marker4Pixels);
618
 
    if( isFourPixels || (markerAttributes.markerStyle() == MarkerAttributes::Marker1Pixel) ){
619
 
        // for high-performance point charts with tiny point markers:
620
 
        painter->setPen( PrintingParameters::scalePen( QPen( brush.color().light() ) ) );
621
 
        if( isFourPixels ){
622
 
            const qreal x = pos.x();
623
 
            const qreal y = pos.y();
624
 
            painter->drawLine( QPointF(x-1.0,y-1.0),
625
 
                               QPointF(x+1.0,y-1.0) );
626
 
            painter->drawLine( QPointF(x-1.0,y),
627
 
                               QPointF(x+1.0,y) );
628
 
            painter->drawLine( QPointF(x-1.0,y+1.0),
629
 
                               QPointF(x+1.0,y+1.0) );
630
 
        }
631
 
        painter->drawPoint( pos );
632
 
    }else{
633
 
        const PainterSaver painterSaver( painter );
634
 
        // we only a solid line surrounding the markers
635
 
        QPen painterPen( pen );
636
 
        painterPen.setStyle( Qt::SolidLine );
637
 
        painter->setPen( PrintingParameters::scalePen( painterPen ) );
638
 
        painter->setBrush( brush );
639
 
        painter->setRenderHint ( QPainter::Antialiasing );
640
 
        painter->translate( pos );
641
 
        switch ( markerAttributes.markerStyle() ) {
642
 
            case MarkerAttributes::MarkerCircle:
643
 
                painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
644
 
                            maSize.height(), maSize.width()) );
645
 
                break;
646
 
            case MarkerAttributes::MarkerSquare:
647
 
                {
648
 
                    QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
649
 
                                maSize.width(), maSize.height() );
650
 
                    painter->drawRect( rect );
651
 
                    break;
652
 
                }
653
 
            case MarkerAttributes::MarkerDiamond:
654
 
                {
655
 
                    QVector <QPointF > diamondPoints;
656
 
                    QPointF top, left, bottom, right;
657
 
                    top    = QPointF( 0, 0 - maSize.height()/2 );
658
 
                    left   = QPointF( 0 - maSize.width()/2, 0 );
659
 
                    bottom = QPointF( 0, maSize.height()/2 );
660
 
                    right  = QPointF( maSize.width()/2, 0 );
661
 
                    diamondPoints << top << left << bottom << right;
662
 
                    painter->drawPolygon( diamondPoints );
663
 
                    break;
664
 
                }
665
 
            // both handled on top of the method:
666
 
            case MarkerAttributes::Marker1Pixel:
667
 
            case MarkerAttributes::Marker4Pixels:
668
 
                    break;
669
 
            case MarkerAttributes::MarkerRing:
670
 
                {
671
 
                    painter->setPen( PrintingParameters::scalePen( QPen( brush.color() ) ) );
672
 
                    painter->setBrush( Qt::NoBrush );
673
 
                    painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
674
 
                                        maSize.height(), maSize.width()) );
675
 
                    break;
676
 
                }
677
 
            case MarkerAttributes::MarkerCross:
678
 
                {
679
 
                    // Note: Markers can have outline,
680
 
                    //       so just drawing two rects is NOT the solution here!
681
 
                    const qreal w02 = maSize.width() * 0.2;
682
 
                    const qreal w05 = maSize.width() * 0.5;
683
 
                    const qreal h02 = maSize.height()* 0.2;
684
 
                    const qreal h05 = maSize.height()* 0.5;
685
 
                    QVector <QPointF > crossPoints;
686
 
                    QPointF p[12];
687
 
                    p[ 0] = QPointF( -w02, -h05 );
688
 
                    p[ 1] = QPointF(  w02, -h05 );
689
 
                    p[ 2] = QPointF(  w02, -h02 );
690
 
                    p[ 3] = QPointF(  w05, -h02 );
691
 
                    p[ 4] = QPointF(  w05,  h02 );
692
 
                    p[ 5] = QPointF(  w02,  h02 );
693
 
                    p[ 6] = QPointF(  w02,  h05 );
694
 
                    p[ 7] = QPointF( -w02,  h05 );
695
 
                    p[ 8] = QPointF( -w02,  h02 );
696
 
                    p[ 9] = QPointF( -w05,  h02 );
697
 
                    p[10] = QPointF( -w05, -h02 );
698
 
                    p[11] = QPointF( -w02, -h02 );
699
 
                    for( int i=0; i<12; ++i )
700
 
                        crossPoints << p[i];
701
 
                    crossPoints << p[0];
702
 
                    painter->drawPolygon( crossPoints );
703
 
                    break;
704
 
                }
705
 
            case MarkerAttributes::MarkerFastCross:
706
 
                {
707
 
                    QPointF left, right, top, bottom;
708
 
                    left  = QPointF( -maSize.width()/2, 0 );
709
 
                    right = QPointF( maSize.width()/2, 0 );
710
 
                    top   = QPointF( 0, -maSize.height()/2 );
711
 
                    bottom= QPointF( 0, maSize.height()/2 );
712
 
                    painter->setPen( PrintingParameters::scalePen( QPen( brush.color() ) ) );
713
 
                    painter->drawLine( left, right );
714
 
                    painter->drawLine(  top, bottom );
715
 
                    break;
716
 
                }
717
 
            default:
718
 
                Q_ASSERT_X ( false, "paintMarkers()",
719
 
                            "Type item does not match a defined Marker Type." );
720
 
        }
721
 
    }
722
 
    painter->setPen( oldPen );
723
 
}
724
 
 
725
 
void AbstractDiagram::paintMarkers( QPainter* painter )
726
 
{
727
 
    if ( !checkInvariants() ) return;
728
 
    const int rowCount = model()->rowCount(rootIndex());
729
 
    const int columnCount = model()->columnCount(rootIndex());
730
 
    for ( int i=datasetDimension()-1; i<columnCount; i += datasetDimension() ) {
731
 
       for ( int j=0; j< rowCount; ++j ) {
732
 
           const QModelIndex index = model()->index( j, i, rootIndex() );
733
 
           double value = model()->data( index ).toDouble();
734
 
           const QPointF pos = coordinatePlane()->translate( QPointF( j, value ) );
735
 
           paintMarker( painter, index, pos );
736
 
       }
737
 
    }
738
 
}
739
 
 
740
 
 
741
 
void AbstractDiagram::setPen( const QModelIndex& index, const QPen& pen )
742
 
{
743
 
    attributesModel()->setData(
744
 
        conditionallyMapFromSource( index ),
745
 
        qVariantFromValue( pen ), DatasetPenRole );
746
 
    emit propertiesChanged();
747
 
}
748
 
 
749
 
void AbstractDiagram::setPen( const QPen& pen )
750
 
{
751
 
    attributesModel()->setModelData(
752
 
        qVariantFromValue( pen ), DatasetPenRole );
753
 
    emit propertiesChanged();
754
 
}
755
 
 
756
 
void AbstractDiagram::setPen( int dataset, const QPen& pen )
757
 
{
758
 
    // To store the pen for a dataset, we use the first column
759
 
    // that's associated with it. (i.e., with a dataset dimension
760
 
    // of two, the column of the keys)
761
 
    const int column = dataset * datasetDimension();
762
 
    
763
 
    attributesModel()->setHeaderData(
764
 
        column, Qt::Horizontal,
765
 
        qVariantFromValue( pen ),
766
 
        DatasetPenRole );
767
 
    emit propertiesChanged();
768
 
}
769
 
 
770
 
QPen AbstractDiagram::pen() const
771
 
{
772
 
    return qVariantValue<QPen>(
773
 
        attributesModel()->data( DatasetPenRole ) );
774
 
}
775
 
 
776
 
QPen AbstractDiagram::pen( int dataset ) const
777
 
{
778
 
    // To store the pen for a dataset, we use the first column
779
 
    // that's associated with it. (i.e., with a dataset dimension
780
 
    // of two, the column of the keys)
781
 
    const int column = dataset * datasetDimension();
782
 
    
783
 
    const QVariant penSettings(
784
 
            attributesModel()->headerData( column, Qt::Horizontal,
785
 
                    DatasetPenRole ) );
786
 
    if( penSettings.isValid() )
787
 
        return qVariantValue< QPen >( penSettings );
788
 
    return pen();
789
 
}
790
 
 
791
 
QPen AbstractDiagram::pen( const QModelIndex& index ) const
792
 
{
793
 
    return qVariantValue<QPen>(
794
 
        attributesModel()->data(
795
 
            conditionallyMapFromSource( index ),
796
 
            DatasetPenRole ) );
797
 
}
798
 
 
799
 
void AbstractDiagram::setBrush( const QModelIndex& index, const QBrush& brush )
800
 
{
801
 
    attributesModel()->setData(
802
 
        conditionallyMapFromSource( index ),
803
 
        qVariantFromValue( brush ), DatasetBrushRole );
804
 
    emit propertiesChanged();
805
 
}
806
 
 
807
 
void AbstractDiagram::setBrush( const QBrush& brush )
808
 
{
809
 
    attributesModel()->setModelData(
810
 
        qVariantFromValue( brush ), DatasetBrushRole );
811
 
    emit propertiesChanged();
812
 
}
813
 
 
814
 
void AbstractDiagram::setBrush( int dataset, const QBrush& brush )
815
 
{
816
 
    // To store the brush for a dataset, we use the first column
817
 
    // that's associated with it. (i.e., with a dataset dimension
818
 
    // of two, the column of the keys)
819
 
    const int column = dataset * datasetDimension();
820
 
    
821
 
    attributesModel()->setHeaderData(
822
 
        column, Qt::Horizontal,
823
 
        qVariantFromValue( brush ),
824
 
        DatasetBrushRole );
825
 
    emit propertiesChanged();
826
 
}
827
 
 
828
 
QBrush AbstractDiagram::brush() const
829
 
{
830
 
    return qVariantValue<QBrush>(
831
 
        attributesModel()->data( DatasetBrushRole ) );
832
 
}
833
 
 
834
 
QBrush AbstractDiagram::brush( int dataset ) const
835
 
{
836
 
    // To store the brush for a dataset, we use the first column
837
 
    // that's associated with it. (i.e., with a dataset dimension
838
 
    // of two, the column of the keys)
839
 
    const int column = dataset * datasetDimension();
840
 
    
841
 
    const QVariant brushSettings(
842
 
            attributesModel()->headerData( column, Qt::Horizontal,
843
 
                    DatasetBrushRole ) );
844
 
    if( brushSettings.isValid() )
845
 
        return qVariantValue< QBrush >( brushSettings );
846
 
    return brush();
847
 
}
848
 
 
849
 
QBrush AbstractDiagram::brush( const QModelIndex& index ) const
850
 
{
851
 
    return qVariantValue<QBrush>(
852
 
        attributesModel()->data( conditionallyMapFromSource( index ), DatasetBrushRole ) );
853
 
}
854
 
 
855
 
/**
856
 
  * Sets the unit prefix for one value
857
 
  * @param prefix the prefix to be set
858
 
  * @param column the value using that prefix
859
 
  * @param orientation the orientantion of the axis to set
860
 
  */
861
 
void AbstractDiagram::setUnitPrefix( const QString& prefix, int column, Qt::Orientation orientation )
862
 
{
863
 
    d->unitPrefixMap[ column ][ orientation ]= prefix;
864
 
}
865
 
 
866
 
/**
867
 
  * Sets the unit prefix for all values
868
 
  * @param prefix the prefix to be set
869
 
  * @param orientation the orientantion of the axis to set
870
 
  */
871
 
void AbstractDiagram::setUnitPrefix( const QString& prefix, Qt::Orientation orientation )
872
 
{
873
 
    d->unitPrefix[ orientation ] = prefix;
874
 
}
875
 
 
876
 
/**
877
 
  * Sets the unit suffix for one value
878
 
  * @param suffix the suffix to be set
879
 
  * @param column the value using that suffix
880
 
  * @param orientation the orientantion of the axis to set
881
 
  */
882
 
void AbstractDiagram::setUnitSuffix( const QString& suffix, int column, Qt::Orientation orientation )
883
 
{
884
 
    d->unitSuffixMap[ column ][ orientation ]= suffix;
885
 
}
886
 
 
887
 
/**
888
 
  * Sets the unit suffix for all values
889
 
  * @param suffix the suffix to be set
890
 
  * @param orientation the orientantion of the axis to set
891
 
  */
892
 
void AbstractDiagram::setUnitSuffix( const QString& suffix, Qt::Orientation orientation )
893
 
{
894
 
    d->unitSuffix[ orientation ] = suffix;
895
 
}
896
 
 
897
 
/**
898
 
  * Returns the unit prefix for a special value
899
 
  * @param column the value which's prefix is requested
900
 
  * @param orientation the orientation of the axis
901
 
  * @param fallback if true, the global prefix is return when no specific one is set for that value
902
 
  * @return the unit prefix
903
 
  */
904
 
QString AbstractDiagram::unitPrefix( int column, Qt::Orientation orientation, bool fallback ) const
905
 
{
906
 
    if( !fallback || d->unitPrefixMap[ column ].contains( orientation ) )
907
 
        return d->unitPrefixMap[ column ][ orientation ];
908
 
    return d->unitPrefix[ orientation ];
909
 
}
910
 
 
911
 
/** Returns the global unit prefix
912
 
  * @param orientation the orientation of the axis
913
 
  * @return the unit prefix
914
 
  */
915
 
QString AbstractDiagram::unitPrefix( Qt::Orientation orientation ) const
916
 
{
917
 
    return d->unitPrefix[ orientation ];
918
 
}
919
 
 
920
 
/**
921
 
  * Returns the unit suffix for a special value
922
 
  * @param column the value which's suffix is requested
923
 
  * @param orientation the orientation of the axis
924
 
  * @param fallback if true, the global suffix is return when no specific one is set for that value
925
 
  * @return the unit suffix
926
 
  */
927
 
QString AbstractDiagram::unitSuffix( int column, Qt::Orientation orientation, bool fallback ) const
928
 
{
929
 
    if( !fallback || d->unitSuffixMap[ column ].contains( orientation ) )
930
 
        return d->unitSuffixMap[ column ][ orientation ];
931
 
    return d->unitSuffix[ orientation ];
932
 
}
933
 
 
934
 
/** Returns the global unit suffix
935
 
  * @param orientation the orientation of the axis
936
 
  * @return the unit siffix
937
 
  */
938
 
QString AbstractDiagram::unitSuffix( Qt::Orientation orientation ) const
939
 
{
940
 
    return d->unitSuffix[ orientation ];
941
 
}
942
 
 
943
 
// implement QAbstractItemView:
944
 
QRect AbstractDiagram::visualRect( const QModelIndex &index ) const
945
 
{
946
 
    return d->reverseMapper.boundingRect( index.row(), index.column() ).toRect();
947
 
}
948
 
 
949
 
void AbstractDiagram::scrollTo(const QModelIndex &, ScrollHint )
950
 
{}
951
 
 
952
 
// indexAt ... down below
953
 
 
954
 
QModelIndex AbstractDiagram::moveCursor(CursorAction, Qt::KeyboardModifiers )
955
 
{ return QModelIndex(); }
956
 
 
957
 
int AbstractDiagram::horizontalOffset() const
958
 
{ return 0; }
959
 
 
960
 
int AbstractDiagram::verticalOffset() const
961
 
{ return 0; }
962
 
 
963
 
bool AbstractDiagram::isIndexHidden(const QModelIndex &) const
964
 
{ return true; }
965
 
 
966
 
void AbstractDiagram::setSelection(const QRect& rect , QItemSelectionModel::SelectionFlags command )
967
 
{
968
 
    const QModelIndexList indexes = d->indexesIn( rect );
969
 
    QItemSelection selection;
970
 
    KDAB_FOREACH( const QModelIndex& index, indexes )
971
 
    {
972
 
        selection.append( QItemSelectionRange( index ) );
973
 
    }
974
 
    selectionModel()->select( selection, command );
975
 
}
976
 
 
977
 
QRegion AbstractDiagram::visualRegionForSelection(const QItemSelection &selection) const
978
 
{
979
 
    QPolygonF polygon;
980
 
    KDAB_FOREACH( const QModelIndex& index, selection.indexes() )
981
 
    {
982
 
        polygon << d->reverseMapper.polygon(index.row(), index.column());
983
 
    }
984
 
    return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
985
 
}
986
 
 
987
 
QRegion AbstractDiagram::visualRegion(const QModelIndex &index) const
988
 
{
989
 
    QPolygonF polygon = d->reverseMapper.polygon(index.row(), index.column());
990
 
    return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
991
 
}
992
 
 
993
 
void KDChart::AbstractDiagram::useDefaultColors( )
994
 
{
995
 
    d->attributesModel->setPaletteType( AttributesModel::PaletteTypeDefault );
996
 
}
997
 
 
998
 
void KDChart::AbstractDiagram::useSubduedColors( )
999
 
{
1000
 
    d->attributesModel->setPaletteType( AttributesModel::PaletteTypeSubdued );
1001
 
}
1002
 
 
1003
 
void KDChart::AbstractDiagram::useRainbowColors( )
1004
 
{
1005
 
    d->attributesModel->setPaletteType( AttributesModel::PaletteTypeRainbow );
1006
 
}
1007
 
 
1008
 
QStringList AbstractDiagram::itemRowLabels() const
1009
 
{
1010
 
    QStringList ret;
1011
 
    if( model() ){
1012
 
        //qDebug() << "AbstractDiagram::itemRowLabels(): " << attributesModel()->rowCount(attributesModelRootIndex()) << "entries";
1013
 
        const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
1014
 
        for( int i = 0; i < rowCount; ++i ){
1015
 
            //qDebug() << "item row label: " << attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString();
1016
 
            ret << unitPrefix( i, Qt::Horizontal, true ) +
1017
 
                   attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString() +
1018
 
                   unitSuffix( i, Qt::Horizontal, true );
1019
 
        }
1020
 
    }
1021
 
    return ret;
1022
 
}
1023
 
 
1024
 
QStringList AbstractDiagram::datasetLabels() const
1025
 
{
1026
 
    QStringList ret;
1027
 
    if( model() == 0 )
1028
 
        return ret;
1029
 
 
1030
 
    const int columnCount = attributesModel()->columnCount(attributesModelRootIndex());
1031
 
    for( int i = 0; i < columnCount; i += datasetDimension() )
1032
 
        ret << attributesModel()->headerData( i, Qt::Horizontal, Qt::DisplayRole ).toString();
1033
 
    
1034
 
    return ret;
1035
 
}
1036
 
 
1037
 
QList<QBrush> AbstractDiagram::datasetBrushes() const
1038
 
{
1039
 
    QList<QBrush> ret;
1040
 
    if( model() == 0 )
1041
 
        return ret;
1042
 
 
1043
 
    const int datasetCount = attributesModel()->columnCount(attributesModelRootIndex()) / datasetDimension();
1044
 
    for ( int dataset = 0; dataset < datasetCount; dataset++ )
1045
 
        ret << brush( dataset );
1046
 
 
1047
 
    return ret;
1048
 
}
1049
 
 
1050
 
QList<QPen> AbstractDiagram::datasetPens() const
1051
 
{
1052
 
    QList<QPen> ret;
1053
 
    if( model() == 0 )
1054
 
        return ret;
1055
 
    
1056
 
    const int datasetCount = attributesModel()->columnCount(attributesModelRootIndex()) / datasetDimension();
1057
 
    for ( int dataset = 0; dataset < datasetCount; dataset++ )
1058
 
        ret << pen( dataset );
1059
 
    
1060
 
    return ret;
1061
 
}
1062
 
 
1063
 
QList<MarkerAttributes> AbstractDiagram::datasetMarkers() const
1064
 
{
1065
 
    QList<MarkerAttributes> ret;
1066
 
    if( model() == 0 )
1067
 
        return ret;
1068
 
    
1069
 
    const int datasetCount = attributesModel()->columnCount(attributesModelRootIndex()) / datasetDimension();
1070
 
    for ( int dataset = 0; dataset < datasetCount; dataset++ )
1071
 
        ret << dataValueAttributes( dataset ).markerAttributes();
1072
 
 
1073
 
    return ret;
1074
 
}
1075
 
 
1076
 
bool AbstractDiagram::checkInvariants( bool justReturnTheStatus ) const
1077
 
{
1078
 
    if( ! justReturnTheStatus ){
1079
 
        Q_ASSERT_X ( model(), "AbstractDiagram::checkInvariants()",
1080
 
                    "There is no usable model set, for the diagram." );
1081
 
 
1082
 
        Q_ASSERT_X ( coordinatePlane(), "AbstractDiagram::checkInvariants()",
1083
 
                    "There is no usable coordinate plane set, for the diagram." );
1084
 
    }
1085
 
    return model() && coordinatePlane();
1086
 
}
1087
 
 
1088
 
int AbstractDiagram::datasetDimension( ) const
1089
 
{
1090
 
    return d->datasetDimension;
1091
 
}
1092
 
 
1093
 
void AbstractDiagram::setDatasetDimension( int dimension )
1094
 
{
1095
 
    Q_UNUSED( dimension );
1096
 
    qDebug() << "Setting the dataset dimension using AbstractDiagram::setDatasetDimension is obsolete. Use the specific diagram types instead.";
1097
 
}
1098
 
 
1099
 
void AbstractDiagram::setDatasetDimensionInternal( int dimension )
1100
 
{
1101
 
    Q_ASSERT( dimension != 0 );
1102
 
    
1103
 
    if ( d->datasetDimension == dimension ) return;
1104
 
    d->datasetDimension = dimension;
1105
 
    setDataBoundariesDirty();
1106
 
    emit layoutChanged( this );
1107
 
}
1108
 
 
1109
 
double AbstractDiagram::valueForCell( int row, int column ) const
1110
 
{
1111
 
    return d->attributesModel->data(
1112
 
            d->attributesModel->index( row, column, attributesModelRootIndex() ) ).toDouble();
1113
 
}
1114
 
 
1115
 
void AbstractDiagram::update() const
1116
 
{
1117
 
    //qDebug("KDChart::AbstractDiagram::update() called");
1118
 
    if( d->plane )
1119
 
        d->plane->update();
1120
 
}
1121
 
 
1122
 
QModelIndex AbstractDiagram::indexAt( const QPoint& point ) const
1123
 
{
1124
 
    return d->indexAt( point );
1125
 
}
1126
 
 
1127
 
QModelIndexList AbstractDiagram::indexesAt( const QPoint& point ) const
1128
 
{
1129
 
    return d->indexesAt( point );
1130
 
}
1131