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

« back to all changes in this revision

Viewing changes to kchart/shape/ChartProxyModel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
61
61
    bool             firstColumnIsLabel;
62
62
    Qt::Orientation  dataDirection;
63
63
    int              dataDimensions;
64
 
    QMap<int, int>   dataMap;
 
64
    
 
65
    QString categoryDataRegion;
 
66
 
 
67
    QVector< CellRegion > dataSetRegions;
65
68
    
66
69
    QList<DataSet*>  dataSets;
67
70
    QList<DataSet*>  removedDataSets;
68
71
    
69
72
    QVector<QRect>   selection;
 
73
 
 
74
    bool automaticDataSetCreation;
70
75
};
71
76
 
72
 
 
73
77
ChartProxyModel::Private::Private()
74
78
{
75
79
    firstRowIsLabel    = false;
76
80
    firstColumnIsLabel = false;
77
81
    dataDimensions     = 1;
 
82
    automaticDataSetCreation = true;
78
83
 
79
 
    dataDirection      = Qt::Vertical; // Apparently the default is columns.
 
84
    // Determines what orientation the data points in a data series
 
85
    // have when multiple data sets are created from one source
 
86
    // region. For example, vertical means that each column in the source
 
87
    // region is assigned to one data series.
 
88
    // Default to Qt::Vertical, as that's what OOo does also.
 
89
    dataDirection      = Qt::Vertical;
80
90
}
81
91
 
82
92
ChartProxyModel::Private::~Private()
100
110
}
101
111
 
102
112
 
 
113
void ChartProxyModel::setAutomaticDataSetCreation( bool enable )
 
114
{
 
115
    d->automaticDataSetCreation = enable;
 
116
}
 
117
 
 
118
bool ChartProxyModel::automaticDataSetCreation() const
 
119
{
 
120
    return d->automaticDataSetCreation;
 
121
}
 
122
 
 
123
#if QT_VERSION < 0x040600
 
124
void ChartProxyModel::beginResetModel()
 
125
{
 
126
}
 
127
 
 
128
void ChartProxyModel::endResetModel()
 
129
{
 
130
    reset();
 
131
}
 
132
#endif
 
133
 
103
134
void ChartProxyModel::rebuildDataMap()
104
135
{
 
136
    if ( !d->automaticDataSetCreation )
 
137
        return;
 
138
 
 
139
    invalidateDataSets();
 
140
    d->dataSets = createDataSetsFromRegion( d->removedDataSets );
 
141
}
 
142
 
 
143
QList<DataSet*> ChartProxyModel::createDataSetsFromRegion( QList<DataSet*> dataSetsToRecycle )
 
144
{
 
145
    QList<DataSet*> createdDataSets;
105
146
    QVector<QRect> dataRegions;
106
147
 
107
148
    if ( d->selection.isEmpty() ) {
154
195
        
155
196
        QMapIterator<int, QVector<QRect> > j( sortedRows );
156
197
        
157
 
        CellRegion categoryDataRegion;
158
 
        
159
 
        if ( d->firstRowIsLabel && j.hasNext() ) {
 
198
        CellRegion category;
 
199
        if ( ! categoryDataRegion().isEmpty() ) {
 
200
            category = CellRegion( categoryDataRegion() );
 
201
        } else if ( d->firstRowIsLabel && j.hasNext() ) {
160
202
            j.next();
161
203
            
162
 
            categoryDataRegion = CellRegion( j.value() );
 
204
            category = CellRegion( j.value() );
163
205
            if ( d->firstColumnIsLabel )
164
 
                categoryDataRegion.subtract( categoryDataRegion.pointAtIndex( 0 ) );
 
206
                category.subtract( category.pointAtIndex( 0 ) );
165
207
        }
166
208
        
167
209
        while ( j.hasNext() ) {
168
210
            j.next();
169
211
            
170
212
            DataSet *dataSet;
171
 
            if ( createdDataSetCount >= d->dataSets.size() ) {
172
 
                if ( !d->removedDataSets.isEmpty() )
173
 
                    dataSet = d->removedDataSets.takeLast();
174
 
                else
175
 
                    dataSet = new DataSet( this );
176
 
 
177
 
                d->dataSets.append( dataSet );
178
 
            }
 
213
            if ( !dataSetsToRecycle.isEmpty() )
 
214
                dataSet = dataSetsToRecycle.takeLast();
179
215
            else
180
 
                dataSet = d->dataSets[createdDataSetCount];
 
216
                dataSet = new DataSet( this );
 
217
            createdDataSets.append( dataSet );
 
218
 
181
219
            dataSet->blockSignals( true );
182
220
            
183
221
            dataSet->setNumber( createdDataSetCount );
184
 
            dataSet->setColor( defaultDataSetColor( createdDataSetCount ) );
185
 
            
186
 
            CellRegion yDataRegion( j.value() );
 
222
            //dataSet->setColor( defaultDataSetColor( createdDataSetCount ) );
 
223
 
187
224
            CellRegion labelDataRegion;
188
 
    
 
225
 
 
226
            CellRegion xDataRegion;
 
227
            // In case of > 1 data dimensions, x data appears before y data
 
228
            if ( d->dataDimensions > 1 )
 
229
                xDataRegion = CellRegion( j.value() );
 
230
 
189
231
            //qDebug() << "Creating data set with region" << j.value();
190
232
            if ( d->firstColumnIsLabel ) {
191
 
                QPoint labelDataPoint = yDataRegion.pointAtIndex( 0 );
 
233
                CellRegion tmpRegion = CellRegion( j.value() );
 
234
                QPoint labelDataPoint = tmpRegion.pointAtIndex( 0 );
192
235
                labelDataRegion = CellRegion( labelDataPoint );
193
 
                
194
 
                yDataRegion.subtract( labelDataPoint );
195
236
            }
 
237
 
 
238
            if ( d->dataDimensions > 1 && j.hasNext() )
 
239
                j.next();
196
240
            
 
241
            CellRegion yDataRegion( j.value() );
 
242
 
 
243
            if ( d->firstColumnIsLabel ) {
 
244
                xDataRegion.subtract( xDataRegion.pointAtIndex( 0 ) );
 
245
                yDataRegion.subtract( yDataRegion.pointAtIndex( 0 ) );
 
246
            }
 
247
 
 
248
            dataSet->setXDataRegion( xDataRegion );
197
249
            dataSet->setYDataRegion( yDataRegion );
198
 
            dataSet->setCategoryDataRegion( categoryDataRegion );
 
250
            dataSet->setCategoryDataRegion( category );
199
251
            dataSet->setLabelDataRegion( labelDataRegion );
200
252
            createdDataSetCount++;
201
253
            dataSet->blockSignals( false );
244
296
        
245
297
        QMapIterator<int, QVector<QRect> > j( sortedColumns );
246
298
        
247
 
        CellRegion categoryDataRegion;
248
 
        
249
 
        if ( d->firstColumnIsLabel && j.hasNext() ) {
 
299
        CellRegion category;
 
300
        if ( ! categoryDataRegion().isEmpty() ) {
 
301
            category = CellRegion( categoryDataRegion() );
 
302
        } else if ( d->firstColumnIsLabel && j.hasNext() ) {
250
303
            j.next();
251
304
            
252
 
            categoryDataRegion = CellRegion( j.value() );
 
305
            category = CellRegion( j.value() );
253
306
            if ( d->firstRowIsLabel )
254
 
                categoryDataRegion.subtract( categoryDataRegion.pointAtIndex( 0 ) );
 
307
                category.subtract( category.pointAtIndex( 0 ) );
255
308
        }
256
309
        
257
310
        while ( j.hasNext() ) {
258
311
            j.next();
259
 
            
 
312
 
260
313
            DataSet *dataSet;
261
 
            if ( createdDataSetCount >= d->dataSets.size() ) {
262
 
                if ( !d->removedDataSets.isEmpty() )
263
 
                    dataSet = d->removedDataSets.takeLast();
264
 
                else
265
 
                    dataSet = new DataSet( this );
266
 
                d->dataSets.append( dataSet );
267
 
            }
 
314
            if ( !dataSetsToRecycle.isEmpty() )
 
315
                dataSet = dataSetsToRecycle.takeLast();
268
316
            else
269
 
                dataSet = d->dataSets[createdDataSetCount];
 
317
                dataSet = new DataSet( this );
 
318
            createdDataSets.append( dataSet );
 
319
 
270
320
            dataSet->blockSignals( true );
271
321
            
272
322
            dataSet->setNumber( createdDataSetCount );
273
 
            dataSet->setColor( defaultDataSetColor( createdDataSetCount ) );
274
 
            
275
 
            CellRegion yDataRegion( j.value() );
 
323
            //dataSet->setColor( defaultDataSetColor( createdDataSetCount ) );
 
324
 
276
325
            CellRegion labelDataRegion;
277
 
    
278
 
            //qDebug() << "Creating data set with region " << j.value();
 
326
            
 
327
            CellRegion xDataRegion;
 
328
            // In case of > 1 data dimensions, x data appears before y data
 
329
            if ( d->dataDimensions > 1 )
 
330
                xDataRegion = CellRegion( j.value() );
 
331
 
 
332
            //qDebug() << "Creating data set with region" << j.value();
279
333
            if ( d->firstRowIsLabel ) {
280
 
                QPoint labelDataPoint = yDataRegion.pointAtIndex( 0 );
 
334
                CellRegion tmpRegion = CellRegion( j.value() );
 
335
                QPoint labelDataPoint = tmpRegion.pointAtIndex( 0 );
281
336
                labelDataRegion = CellRegion( labelDataPoint );
282
 
                
283
 
                yDataRegion.subtract( labelDataPoint );
284
337
            }
 
338
 
 
339
            if ( d->dataDimensions > 1 && j.hasNext() )
 
340
                j.next();
285
341
            
 
342
            CellRegion yDataRegion( j.value() );
 
343
 
 
344
            if ( d->firstRowIsLabel ) {
 
345
                xDataRegion.subtract( xDataRegion.pointAtIndex( 0 ) );
 
346
                yDataRegion.subtract( yDataRegion.pointAtIndex( 0 ) );
 
347
            }
 
348
 
 
349
            dataSet->setXDataRegion( xDataRegion );
286
350
            dataSet->setYDataRegion( yDataRegion );
287
351
            dataSet->setLabelDataRegion( labelDataRegion );
288
 
            dataSet->setCategoryDataRegion( categoryDataRegion );
 
352
            dataSet->setCategoryDataRegion( category );
289
353
            createdDataSetCount++;
290
354
            dataSet->blockSignals( false );
291
355
        }
292
356
    }
293
 
    
294
 
    while ( d->dataSets.size() > createdDataSetCount ) {
295
 
        DataSet *dataSet = d->dataSets.takeLast();
296
 
 
297
 
        // TODO: Restore attached axis when dataset is re-inserted?
298
 
        if ( dataSet->attachedAxis() )
299
 
            dataSet->attachedAxis()->detachDataSet( dataSet, true );
300
 
 
301
 
        d->removedDataSets.append( dataSet );
302
 
    }
 
357
 
 
358
    return createdDataSets;
303
359
}
304
360
 
305
361
 
308
364
    if ( this->sourceModel() == sourceModel )
309
365
        return;
310
366
 
 
367
    beginResetModel();
 
368
 
311
369
    if ( this->sourceModel() ) {
 
370
        disconnect( this->sourceModel(), SIGNAL( modelReset() ),
 
371
                    this,                SLOT( slotModelReset() ) );
312
372
        disconnect( this->sourceModel(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
313
373
                    this,                SLOT( dataChanged( const QModelIndex&, const QModelIndex& ) ) );
314
374
        disconnect( this->sourceModel(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
322
382
    }
323
383
 
324
384
    if ( sourceModel ) {
 
385
        connect( sourceModel, SIGNAL( modelReset() ),
 
386
                 this,        SLOT( slotModelReset() ) );
325
387
        connect( sourceModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
326
388
                 this,        SLOT( dataChanged( const QModelIndex&, const QModelIndex& ) ) );
327
389
        connect( sourceModel, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
337
399
    QAbstractProxyModel::setSourceModel( sourceModel );
338
400
    
339
401
    rebuildDataMap();
340
 
 
341
 
    // Update the entire data set
342
 
    reset();
 
402
    endResetModel();
343
403
}
344
404
 
345
 
void ChartProxyModel::setSourceModel( QAbstractItemModel *sourceModel, 
 
405
void ChartProxyModel::setSourceModel( QAbstractItemModel *model,
346
406
                                      const QVector<QRect> &selection )
347
407
{
348
 
    // FIXME: What if we already have a source model?  Don't we have
349
 
    //        to disconnect that one before connecting the new one?
350
 
 
351
 
    connect( sourceModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
352
 
             this,        SLOT( dataChanged( const QModelIndex&, const QModelIndex& ) ) );
353
 
    
354
408
    d->selection = selection;
355
 
 
356
 
    QAbstractProxyModel::setSourceModel( sourceModel );
357
 
    
358
 
    rebuildDataMap();
359
 
 
360
 
    // Update the entire data set
361
 
    reset();
 
409
    setSourceModel( model );
362
410
}
363
411
 
364
412
void ChartProxyModel::setSelection( const QVector<QRect> &selection )
369
417
 
370
418
void ChartProxyModel::saveOdf( KoShapeSavingContext &context ) const
371
419
{
372
 
    KoXmlWriter &bodyWriter = context.xmlWriter();
373
 
    KoGenStyles &mainStyles = context.mainStyles();
374
 
    
375
 
    foreach ( DataSet *dataSet, d->dataSets ) {
376
 
        bodyWriter.startElement( "chart:series" );
377
 
        
378
 
        KoGenStyle style( KoGenStyle::StyleGraphicAuto, "chart" );
379
 
        
380
 
        if ( dataSet->chartType() != LastChartType )
381
 
            style.addProperty( "chart:family", ODF_CHARTTYPES[ dataSet->chartType() ] );
382
 
            
383
 
        KoOdfGraphicStyles::saveOdfFillStyle( style, mainStyles, dataSet->brush() );
384
 
        KoOdfGraphicStyles::saveOdfStrokeStyle( style, mainStyles, dataSet->pen() );
385
 
            
386
 
        // TODO: Save external data sources also
387
 
        const QString prefix( "local-table." );
388
 
        
389
 
        // Save cell regions
390
 
        bodyWriter.addAttribute( "chart:values-cell-range-address", prefix + dataSet->yDataRegionString() );
391
 
        bodyWriter.addAttribute( "chart:label-cell-address", prefix + dataSet->labelDataRegionString() );
392
 
        
393
 
        const QString styleName = mainStyles.lookup( style, "ch", KoGenStyles::ForceNumbering );
394
 
        bodyWriter.addAttribute( "chart:style-name", styleName );
395
 
        
396
 
        bodyWriter.endElement(); // chart:series
397
 
    }
 
420
    foreach ( DataSet *dataSet, d->dataSets )
 
421
        dataSet->saveOdf( context );
398
422
}
399
423
 
400
424
// This loads the properties of the datasets (chart:series).
402
426
bool ChartProxyModel::loadOdf( const KoXmlElement &element,
403
427
                               KoShapeLoadingContext &context )
404
428
{
 
429
    beginResetModel();
405
430
    KoStyleStack &styleStack = context.odfLoadingContext().styleStack();
406
431
    styleStack.save();
407
432
 
408
 
    d->dataSets.clear();
 
433
    invalidateDataSets();
 
434
 
 
435
    QList<DataSet*> createdDataSets;
 
436
    int loadedDataSetCount = 0;
 
437
 
 
438
    // A cell range for all data is optional.
 
439
    // If it is specified, use createDataSetsFromRegion() to automatically
 
440
    // turn this data region into consecutive data series.
 
441
    // If cell ranges are in addition specified for one or more of these
 
442
    // data series, they'll be overwritten by these values.
 
443
    if ( element.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) )
 
444
    {
 
445
        QString cellRangeAddress = element.attributeNS( KoXmlNS::table, "cell-range-address" );
 
446
        setSelection( CellRegion::stringToRegion( cellRangeAddress ) );
 
447
        createdDataSets = createDataSetsFromRegion( d->removedDataSets );
 
448
    }
409
449
 
410
450
    KoXmlElement n;
411
451
    forEachElement ( n, element ) {
413
453
            continue;
414
454
 
415
455
        if ( n.localName() == "series" ) {
416
 
            DataSet *dataSet = new DataSet( this );
417
 
            dataSet->setNumber( d->dataSets.size() );
 
456
            DataSet *dataSet;
 
457
            if ( loadedDataSetCount < createdDataSets.size() ) {
 
458
                dataSet = createdDataSets[loadedDataSetCount];
 
459
            } else {
 
460
                dataSet = new DataSet( this );
 
461
                dataSet->setNumber( d->dataSets.size() );
 
462
            }
418
463
            d->dataSets.append( dataSet );
419
 
 
420
 
            if ( n.hasAttributeNS( KoXmlNS::chart, "style-name" ) ) {
421
 
                //qDebug() << "HAS style-name:" << n.attributeNS( KoXmlNS::chart, "style-name" );
422
 
                styleStack.clear();
423
 
                context.odfLoadingContext().fillStyleStack( n, KoXmlNS::chart, "style-name", "chart" );
424
 
 
425
 
                //styleStack.setTypeProperties( "chart" );
426
 
 
427
 
                // FIXME: Load Pie explode factors
428
 
                //if ( styleStack.hasProperty( KoXmlNS::chart, "pie-offset" ) )
429
 
                //    setPieExplodeFactor( dataSet, styleStack.property( KoXmlNS::chart, "pie-offset" ).toInt() );
430
 
 
431
 
                styleStack.setTypeProperties( "graphic" );
432
 
 
433
 
                if ( styleStack.hasProperty( KoXmlNS::draw, "stroke" ) ) {
434
 
                    qDebug() << "HAS stroke";
435
 
                    QString stroke = styleStack.property( KoXmlNS::draw, "stroke" );
436
 
                    if( stroke == "solid" || stroke == "dash" ) {
437
 
                        QPen pen = KoOdfGraphicStyles::loadOdfStrokeStyle( styleStack, stroke, context.odfLoadingContext().stylesReader() );
438
 
                        dataSet->setPen( pen );
439
 
                    }
440
 
                }
441
 
 
442
 
                if ( styleStack.hasProperty( KoXmlNS::draw, "fill" ) ) {
443
 
                    //qDebug() << "HAS fill";
444
 
                    QString fill = styleStack.property( KoXmlNS::draw, "fill" );
445
 
                    QBrush brush;
446
 
                    if ( fill == "solid" || fill == "hatch" ) {
447
 
                        brush = KoOdfGraphicStyles::loadOdfFillStyle( styleStack, fill, context.odfLoadingContext().stylesReader() );
448
 
                    } else if ( fill == "gradient" ) {
449
 
                        brush = KoOdfGraphicStyles::loadOdfGradientStyle( styleStack, context.odfLoadingContext().stylesReader(), QSizeF( 5.0, 60.0 ) );
450
 
                    } else if ( fill == "bitmap" )
451
 
                        brush = KoOdfGraphicStyles::loadOdfPatternStyle( styleStack, context.odfLoadingContext(), QSizeF( 5.0, 60.0 ) );
452
 
                    dataSet->setBrush( brush );
453
 
                } else {
454
 
                    dataSet->setColor( defaultDataSetColor( dataSet->number() ) );
455
 
                }
456
 
            }
457
 
 
458
 
            if ( n.hasAttributeNS( KoXmlNS::chart, "values-cell-range-address" ) ) {
459
 
                const QString region = n.attributeNS( KoXmlNS::chart, "values-cell-range-address", QString() );
460
 
                dataSet->setYDataRegionString( region );
461
 
            }
462
 
            if ( n.hasAttributeNS( KoXmlNS::chart, "label-cell-address" ) ) {
463
 
                const QString region = n.attributeNS( KoXmlNS::chart, "label-cell-address", QString() );
464
 
                dataSet->setLabelDataRegionString( region );
465
 
            }
466
 
 
467
 
            KoXmlElement m;
468
 
            forEachElement ( m, n ) {
469
 
                if ( m.namespaceURI() != KoXmlNS::chart )
470
 
                    continue;
471
 
                // FIXME: Load data points
472
 
            }
 
464
            dataSet->loadOdf( n, context );
 
465
 
 
466
            loadedDataSetCount++;
473
467
        } else {
474
468
            qWarning() << "ChartProxyModel::loadOdf(): Unknown tag name \"" << n.localName() << "\"";
475
469
        }
476
470
    }
477
471
 
478
 
    rebuildDataMap();
479
 
    reset();
 
472
    //rebuildDataMap();
 
473
    endResetModel();
480
474
 
481
475
    styleStack.restore();
482
476
    return true;
513
507
    QRect dataChangedRect = QRect( topLeftPoint,
514
508
                                   QSize( bottomRightPoint.x() - topLeftPoint.x() + 1,
515
509
                                          bottomRightPoint.y() - topLeftPoint.y() + 1 ) );
516
 
    
 
510
 
517
511
    foreach ( DataSet *dataSet, d->dataSets ) {
518
 
        bool intersects = false;
519
 
        QRect changedRect;
520
 
        foreach ( const QRect &rect, dataSet->yDataRegion().rects() ) {
521
 
            if ( rect.intersects( dataChangedRect ) ) {
522
 
                changedRect |= rect.intersected( dataChangedRect );
523
 
                intersects = true;
524
 
 
525
 
                break;
526
 
            }
527
 
        }
528
 
 
529
 
        if ( intersects ) {
530
 
            dataSet->yDataChanged( changedRect );
531
 
        }
 
512
        if ( dataSet->xDataRegion().intersects( dataChangedRect ) )
 
513
            dataSet->xDataChanged( dataSet->xDataRegion().intersected( dataChangedRect ).boundingRect() );
 
514
 
 
515
        if ( dataSet->yDataRegion().intersects( dataChangedRect ) )
 
516
            dataSet->yDataChanged( dataSet->yDataRegion().intersected( dataChangedRect ).boundingRect() );
 
517
 
 
518
        if ( dataSet->categoryDataRegion().intersects( dataChangedRect ) )
 
519
            dataSet->categoryDataChanged( dataSet->categoryDataRegion().intersected( dataChangedRect ).boundingRect() );
 
520
 
 
521
        if ( dataSet->labelDataRegion().intersects( dataChangedRect ) )
 
522
            dataSet->labelDataChanged( dataSet->labelDataRegion().intersected( dataChangedRect ).boundingRect() );
 
523
 
 
524
        if ( dataSet->customDataRegion().intersects( dataChangedRect ) )
 
525
            dataSet->customDataChanged( dataSet->customDataRegion().intersected( dataChangedRect ).boundingRect() );
532
526
    }
533
527
        
534
528
    emit dataChanged();
617
611
 
618
612
QModelIndex ChartProxyModel::mapFromSource( const QModelIndex &sourceIndex ) const
619
613
{
620
 
    int  row;
621
 
    int  column;
622
 
 
623
 
    if ( d->dataDirection == Qt::Horizontal ) {
624
 
        row    = sourceIndex.row();
625
 
        column = sourceIndex.column();
626
 
 
627
 
        if ( d->firstRowIsLabel )
628
 
            row--;
629
 
        if ( d->firstColumnIsLabel )
630
 
            column--;
631
 
        
632
 
        // Find the first occurrence of row in the map
633
 
        for ( int i = 0; i < d->dataMap.size(); i++ ) {
634
 
            if ( d->dataMap[i] == row ) {
635
 
                row = i;
636
 
                break;
637
 
            }
638
 
        }
639
 
    }
640
 
    else {
641
 
        // d->dataDirection == Qt::Vertical here
642
 
 
643
 
        row    = sourceIndex.column();
644
 
        column = sourceIndex.row();
645
 
 
646
 
        if ( d->firstRowIsLabel )
647
 
            row--;
648
 
        if ( d->firstColumnIsLabel )
649
 
            column--;
650
 
        
651
 
        // Find the first occurrence of column in the map
652
 
        for ( int i = 0; i < d->dataMap.size(); i++ ) {
653
 
            if ( d->dataMap[i] == column ) {
654
 
                column = i;
655
 
                break;
656
 
            }
657
 
        }
658
 
    }
659
 
    
660
 
    return sourceModel()->index( row, column );
 
614
    Q_UNUSED( sourceIndex );
 
615
    return QModelIndex();
661
616
}
662
617
 
663
618
QModelIndex ChartProxyModel::mapToSource( const QModelIndex &proxyIndex ) const
664
619
{
665
 
    int  row;
666
 
    int  column;
667
 
 
668
 
    if ( d->dataDirection == Qt::Horizontal ) {
669
 
        row    = d->dataMap[ proxyIndex.row() ];
670
 
        column = proxyIndex.column();
671
 
    }
672
 
    else {
673
 
        row    = proxyIndex.column();
674
 
        column = d->dataMap[ proxyIndex.row() ];
675
 
    }
676
 
 
677
 
    if ( d->firstRowIsLabel )
678
 
        row++;
679
 
    if ( d->firstColumnIsLabel )
680
 
        column++;
681
 
 
682
 
    return sourceModel()->index( row, column );
 
620
    Q_UNUSED( proxyIndex );
 
621
    return QModelIndex();
683
622
}
684
623
 
685
624
 
773
712
{
774
713
    if ( b == d->firstRowIsLabel )
775
714
        return;
 
715
 
 
716
    beginResetModel();
776
717
    
777
718
    d->firstRowIsLabel = b;
778
719
    
780
721
        return;
781
722
    
782
723
    rebuildDataMap();
783
 
    reset();
 
724
    endResetModel();
784
725
}
785
726
 
786
727
 
788
729
{
789
730
    if ( b == d->firstColumnIsLabel )
790
731
        return;
791
 
    
 
732
 
 
733
    beginResetModel();
792
734
    d->firstColumnIsLabel = b;
793
735
 
794
736
    if ( !sourceModel() )
795
737
        return;
796
738
    
797
739
    rebuildDataMap();
798
 
    reset();
 
740
    endResetModel();
799
741
}
800
742
 
801
743
Qt::Orientation ChartProxyModel::dataDirection()
803
745
    return d->dataDirection;
804
746
}
805
747
 
 
748
void ChartProxyModel::invalidateDataSets()
 
749
{
 
750
    foreach ( DataSet *dataSet, d->dataSets )
 
751
    {
 
752
        if ( dataSet->attachedAxis() ) {
 
753
            // Remove data sets 'silently'. Once the last data set
 
754
            // has been detached from an axis, the axis will delete
 
755
            // all models and diagrams associated with it, thus we
 
756
            // do not need to propagate these events to any models.
 
757
            dataSet->attachedAxis()->detachDataSet( dataSet, true );
 
758
        }
 
759
    }
 
760
 
 
761
    d->removedDataSets = d->dataSets;
 
762
    d->dataSets.clear();
 
763
}
 
764
 
806
765
void ChartProxyModel::setDataDirection( Qt::Orientation orientation )
807
766
{
808
767
    if ( d->dataDirection == orientation )
809
768
        return;
810
769
 
 
770
    beginResetModel();
811
771
    d->dataDirection = orientation;
812
772
 
813
773
    if ( !sourceModel() )
814
774
        return;
815
 
    
 
775
 
816
776
    rebuildDataMap();
817
 
    reset();
 
777
    endResetModel();
818
778
}
819
779
 
820
780
void ChartProxyModel::setDataDimensions( int dimensions )
822
782
    if ( d->dataDimensions == dimensions )
823
783
        return;
824
784
 
 
785
    beginResetModel();
825
786
    d->dataDimensions = dimensions;
826
787
 
827
788
    rebuildDataMap();
828
 
    reset();
 
789
    endResetModel();
829
790
}
830
791
 
831
792
bool ChartProxyModel::firstRowIsLabel() const
838
799
    return d->firstColumnIsLabel;
839
800
}
840
801
 
 
802
QString ChartProxyModel::categoryDataRegion() const
 
803
{
 
804
    return d->categoryDataRegion;
 
805
}
 
806
 
 
807
void ChartProxyModel::setCategoryDataRegion(const QString& region)
 
808
{
 
809
    d->categoryDataRegion = region;
 
810
}
 
811
 
841
812
QList<DataSet*> ChartProxyModel::dataSets() const
842
813
{
843
814
    return d->dataSets;
850
821
    Q_UNUSED( start );
851
822
    Q_UNUSED( end );
852
823
 
 
824
    beginResetModel();
853
825
    rebuildDataMap();
854
 
    reset();
 
826
    endResetModel();
855
827
}
856
828
 
857
829
void ChartProxyModel::slotColumnsInserted( const QModelIndex &parent,
861
833
    Q_UNUSED( start );
862
834
    Q_UNUSED( end );
863
835
 
 
836
    beginResetModel();
864
837
    rebuildDataMap();
865
 
    reset();
 
838
    endResetModel();
866
839
}
867
840
 
868
841
void ChartProxyModel::slotRowsRemoved( const QModelIndex &parent,
872
845
    Q_UNUSED( start );
873
846
    Q_UNUSED( end );
874
847
 
 
848
    beginResetModel();
875
849
    rebuildDataMap();
876
 
    reset();
 
850
    endResetModel();
877
851
}
878
852
 
879
853
void ChartProxyModel::slotColumnsRemoved( const QModelIndex &parent,
883
857
    Q_UNUSED( start );
884
858
    Q_UNUSED( end );
885
859
 
 
860
    beginResetModel();
886
861
    rebuildDataMap();
887
 
    reset();
 
862
    endResetModel();
888
863
}
889
864
 
890
 
void ChartProxyModel::reset()
 
865
void ChartProxyModel::slotModelReset()
891
866
{
892
 
    QAbstractProxyModel::reset();
893
 
    emit modelResetComplete();
 
867
    rebuildDataMap();
 
868
    reset(); // propagate
894
869
}
895
870
 
896
 
 
897
871
#include "ChartProxyModel.moc"