1 /*
2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3 *
4 * This file is part of the KD Chart library.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "KChartAttributesModel.h"
21
22 #include "KChartPalette.h"
23 #include "KChartGlobal.h"
24 #include "KChartMath_p.h"
25
26 #include <QDebug>
27 #include <QPen>
28 #include <QPointer>
29
30 #include <KChartTextAttributes.h>
31 #include <KChartFrameAttributes.h>
32 #include <KChartBackgroundAttributes.h>
33 #include <KChartDataValueAttributes.h>
34 #include <KChartMarkerAttributes.h>
35 #include <KChartBarAttributes.h>
36 #include <KChartStockBarAttributes.h>
37 #include <KChartLineAttributes.h>
38 #include <KChartPieAttributes.h>
39 #include <KChartAbstractThreeDAttributes.h>
40 #include <KChartThreeDBarAttributes.h>
41 #include <KChartThreeDLineAttributes.h>
42 #include <KChartThreeDPieAttributes.h>
43 #include <KChartGridAttributes.h>
44 #include <KChartValueTrackerAttributes.h>
45
46
47 using namespace KChart;
48
49
50 class Q_DECL_HIDDEN AttributesModel::Private
51 {
52 public:
53 Private();
54
55 QMap< int, QMap< int, QMap< int, QVariant > > > dataMap;
56 QMap< int, QMap< int, QVariant > > horizontalHeaderDataMap;
57 QMap< int, QMap< int, QVariant > > verticalHeaderDataMap;
58 QMap< int, QVariant > modelDataMap;
59 QMap< int, QVariant > defaultsMap;
60 int dataDimension;
61 AttributesModel::PaletteType paletteType;
62 Palette palette;
63 };
64
Private()65 AttributesModel::Private::Private()
66 : dataDimension( 1 ),
67 paletteType( AttributesModel::PaletteTypeDefault ),
68 palette( Palette::defaultPalette() )
69 {
70 }
71
72 #define d d_func()
73
AttributesModel(QAbstractItemModel * model,QObject * parent)74 AttributesModel::AttributesModel( QAbstractItemModel* model, QObject * parent/* = 0 */ )
75 : AbstractProxyModel( parent ),
76 _d( new Private )
77 {
78 setSourceModel( model );
79 setDefaultForRole( KChart::DataValueLabelAttributesRole,
80 DataValueAttributes::defaultAttributesAsVariant() );
81 }
82
~AttributesModel()83 AttributesModel::~AttributesModel()
84 {
85 delete _d;
86 _d = nullptr;
87 }
88
initFrom(const AttributesModel * other)89 void AttributesModel::initFrom( const AttributesModel* other )
90 {
91 *d = *other->d;
92 }
93
compareHeaderDataMaps(const QMap<int,QMap<int,QVariant>> & mapA,const QMap<int,QMap<int,QVariant>> & mapB) const94 bool AttributesModel::compareHeaderDataMaps( const QMap< int, QMap< int, QVariant > >& mapA,
95 const QMap< int, QMap< int, QVariant > >& mapB ) const
96 {
97 if ( mapA.count() != mapB.count() ) {
98 return false;
99 }
100 QMap< int, QMap< int, QVariant > >::const_iterator itA = mapA.constBegin();
101 QMap< int, QMap< int, QVariant > >::const_iterator itB = mapB.constBegin();
102 for ( ; itA != mapA.constEnd(); ++itA, ++itB ) {
103 if ( itA->count() != itB->count() ) {
104 return false;
105 }
106 QMap< int, QVariant >::const_iterator it2A = itA->constBegin();
107 QMap< int, QVariant >::const_iterator it2B = itB->constBegin();
108 for ( ; it2A != itA->constEnd(); ++it2A, ++it2B ) {
109 if ( it2A.key() != it2B.key() ) {
110 return false;
111 }
112 if ( !compareAttributes( it2A.key(), it2A.value(), it2B.value() ) ) {
113 return false;
114 }
115 }
116 }
117 return true;
118 }
119
compare(const AttributesModel * other) const120 bool AttributesModel::compare( const AttributesModel* other ) const
121 {
122 if ( other == this ) {
123 return true;
124 }
125 if ( !other || d->paletteType != other->d->paletteType ) {
126 return false;
127 }
128
129 {
130 if ( d->dataMap.count() != other->d->dataMap.count() ) {
131 return false;
132 }
133 QMap< int, QMap< int, QMap<int, QVariant > > >::const_iterator itA = d->dataMap.constBegin();
134 QMap< int, QMap< int, QMap<int, QVariant > > >::const_iterator itB = other->d->dataMap.constBegin();
135 for ( ; itA != d->dataMap.constEnd(); ++itA, ++itB ) {
136 if ( itA->count() != itB->count() ) {
137 return false;
138 }
139 QMap< int, QMap< int, QVariant > >::const_iterator it2A = itA->constBegin();
140 QMap< int, QMap< int, QVariant > >::const_iterator it2B = itB->constBegin();
141 for ( ; it2A != itA->constEnd(); ++it2A, ++it2B ) {
142 if ( it2A->count() != it2B->count() ) {
143 return false;
144 }
145 QMap< int, QVariant >::const_iterator it3A = it2A->constBegin();
146 QMap< int, QVariant >::const_iterator it3B = it2B->constBegin();
147 for ( ; it3A != it2A->constEnd(); ++it3A, ++it3B ) {
148 if ( it3A.key() != it3B.key() ) {
149 return false;
150 }
151 if ( !compareAttributes( it3A.key(), it3A.value(), it3B.value() ) ) {
152 return false;
153 }
154 }
155 }
156 }
157 }
158
159 if ( !compareHeaderDataMaps( d->horizontalHeaderDataMap, other->d->horizontalHeaderDataMap ) ||
160 !compareHeaderDataMaps( d->verticalHeaderDataMap, other->d->verticalHeaderDataMap ) ) {
161 return false;
162 }
163
164 {
165 if ( d->modelDataMap.count() != other->d->modelDataMap.count() ) {
166 return false;
167 }
168 QMap< int, QVariant >::const_iterator itA = d->modelDataMap.constBegin();
169 QMap< int, QVariant >::const_iterator itB = other->d->modelDataMap.constBegin();
170 for ( ; itA != d->modelDataMap.constEnd(); ++itA, ++itB ) {
171 if ( itA.key() != itB.key() ) {
172 return false;
173 }
174 if ( !compareAttributes( itA.key(), itA.value(), itB.value() ) ) {
175 return false;
176 }
177 }
178 }
179 return true;
180 }
181
compareAttributes(int role,const QVariant & a,const QVariant & b) const182 bool AttributesModel::compareAttributes(
183 int role, const QVariant& a, const QVariant& b ) const
184 {
185 if ( isKnownAttributesRole( role ) ) {
186 switch ( role ) {
187 case DataValueLabelAttributesRole:
188 return (a.value<DataValueAttributes>() ==
189 b.value<DataValueAttributes>());
190 case DatasetBrushRole:
191 return (a.value<QBrush>() ==
192 b.value<QBrush>());
193 case DatasetPenRole:
194 return (a.value<QPen>() ==
195 b.value<QPen>());
196 case ThreeDAttributesRole:
197 // As of yet there is no ThreeDAttributes class,
198 // and the AbstractThreeDAttributes class is pure virtual,
199 // so we ignore this role for now.
200 // (khz, 04.04.2007)
201 /*
202 return (qVariantValue<ThreeDAttributes>( a ) ==
203 qVariantValue<ThreeDAttributes>( b ));
204 */
205 break;
206 case LineAttributesRole:
207 return (a.value<LineAttributes>() ==
208 b.value<LineAttributes>());
209 case ThreeDLineAttributesRole:
210 return (a.value<ThreeDLineAttributes>() ==
211 b.value<ThreeDLineAttributes>());
212 case BarAttributesRole:
213 return (a.value<BarAttributes>() ==
214 b.value<BarAttributes>());
215 case StockBarAttributesRole:
216 return (a.value<StockBarAttributes>() ==
217 b.value<StockBarAttributes>());
218 case ThreeDBarAttributesRole:
219 return (a.value<ThreeDBarAttributes>() ==
220 b.value<ThreeDBarAttributes>());
221 case PieAttributesRole:
222 return (a.value<PieAttributes>() ==
223 b.value<PieAttributes>());
224 case ThreeDPieAttributesRole:
225 return (a.value<ThreeDPieAttributes>() ==
226 b.value<ThreeDPieAttributes>());
227 case ValueTrackerAttributesRole:
228 return (a.value<ValueTrackerAttributes>() ==
229 b.value<ValueTrackerAttributes>());
230 case DataHiddenRole:
231 return (a.value<bool>() ==
232 b.value<bool>());
233 default:
234 Q_ASSERT( false ); // all of our own roles need to be handled
235 break;
236 }
237 } else {
238 return (a == b);
239 }
240 return true;
241 }
242
243
headerData(int section,Qt::Orientation orientation,int role) const244 QVariant AttributesModel::headerData( int section, Qt::Orientation orientation,
245 int role/* = Qt::DisplayRole */ ) const
246 {
247 if ( sourceModel() ) {
248 const QVariant sourceData = sourceModel()->headerData( section, orientation, role );
249 if ( sourceData.isValid() ) {
250 return sourceData;
251 }
252 }
253
254 // the source model didn't have data set, let's use our stored values
255 const QMap< int, QMap< int, QVariant> >& map = orientation == Qt::Horizontal ?
256 d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
257 QMap< int, QMap< int, QVariant > >::const_iterator mapIt = map.find( section );
258 if ( mapIt != map.constEnd() ) {
259 const QMap< int, QVariant >& dataMap = mapIt.value();
260 QMap< int, QVariant >::const_iterator dataMapIt = dataMap.find( role );
261 if ( dataMapIt != dataMap.constEnd() ) {
262 return dataMapIt.value();
263 }
264 }
265
266 return defaultHeaderData( section, orientation, role );
267 }
268
269
defaultHeaderData(int section,Qt::Orientation orientation,int role) const270 QVariant AttributesModel::defaultHeaderData( int section, Qt::Orientation orientation, int role ) const
271 {
272 // Default values if nothing else matches
273
274 const int dataset = section / d->dataDimension;
275
276 switch ( role ) {
277 case Qt::DisplayRole:
278 //TODO for KChart 3.0: return QString::number( dataset + 1 );
279 return QVariant( (orientation == Qt::Vertical ? QStringLiteral("Series ") : QStringLiteral("Item ")) + QString::number( dataset )) ;
280 case KChart::DatasetBrushRole:
281 return d->palette.getBrush( dataset );
282 case KChart::DatasetPenRole:
283 // if no per model override was set, use the (possibly default) color set for the brush
284 if ( !modelData( role ).isValid() ) {
285 QBrush brush = headerData( section, orientation, DatasetBrushRole ).value< QBrush >();
286 return QPen( brush.color() );
287 }
288 default:
289 break;
290 }
291
292 return QVariant();
293 }
294
295
data(int role) const296 QVariant AttributesModel::data( int role ) const
297 {
298 if ( isKnownAttributesRole( role ) ) {
299 // check if there is something set at global level
300 QVariant v = modelData( role );
301
302 // else return the default setting, if any
303 if ( !v.isValid() )
304 v = defaultsForRole( role );
305 return v;
306 }
307 return QVariant();
308 }
309
310
data(int column,int role) const311 QVariant AttributesModel::data( int column, int role ) const
312 {
313 if ( isKnownAttributesRole( role ) ) {
314 // check if there is something set for the column (dataset)
315 QVariant v;
316 v = headerData( column, Qt::Horizontal, role );
317
318 // check if there is something set at global level
319 if ( !v.isValid() )
320 v = data( role ); // includes automatic fallback to default
321 return v;
322 }
323 return QVariant();
324 }
325
326
data(const QModelIndex & index,int role) const327 QVariant AttributesModel::data( const QModelIndex& index, int role ) const
328 {
329 if ( index.isValid() ) {
330 Q_ASSERT( index.model() == this );
331 }
332 if ( !sourceModel() ) {
333 return QVariant();
334 }
335
336 if ( index.isValid() ) {
337 const QVariant sourceData = sourceModel()->data( mapToSource( index ), role );
338 if ( sourceData.isValid() ) {
339 return sourceData;
340 }
341 }
342
343 // check if we are storing a value for this role at this cell index
344 if ( d->dataMap.contains( index.column() ) ) {
345 const QMap< int, QMap< int, QVariant > >& colDataMap = d->dataMap[ index.column() ];
346 if ( colDataMap.contains( index.row() ) ) {
347 const QMap< int, QVariant >& dataMap = colDataMap[ index.row() ];
348 if ( dataMap.contains( role ) ) {
349 const QVariant v = dataMap[ role ];
350 if ( v.isValid() ) {
351 return v;
352 }
353 }
354 }
355 }
356 // check if there is something set for the column (dataset), or at global level
357 if ( index.isValid() ) {
358 return data( index.column(), role ); // includes automatic fallback to default
359 }
360
361 return QVariant();
362 }
363
364
isKnownAttributesRole(int role) const365 bool AttributesModel::isKnownAttributesRole( int role ) const
366 {
367 switch ( role ) {
368 // fallthrough intended
369 case DataValueLabelAttributesRole:
370 case DatasetBrushRole:
371 case DatasetPenRole:
372 case ThreeDAttributesRole:
373 case LineAttributesRole:
374 case ThreeDLineAttributesRole:
375 case BarAttributesRole:
376 case StockBarAttributesRole:
377 case ThreeDBarAttributesRole:
378 case PieAttributesRole:
379 case ThreeDPieAttributesRole:
380 case ValueTrackerAttributesRole:
381 case DataHiddenRole:
382 return true;
383 default:
384 return false;
385 }
386 }
387
defaultsForRole(int role) const388 QVariant AttributesModel::defaultsForRole( int role ) const
389 {
390 // returns default-constructed QVariant if not found
391 return d->defaultsMap.value( role );
392 }
393
setData(const QModelIndex & index,const QVariant & value,int role)394 bool AttributesModel::setData ( const QModelIndex & index, const QVariant & value, int role )
395 {
396 if ( !isKnownAttributesRole( role ) ) {
397 return sourceModel()->setData( mapToSource(index), value, role );
398 } else {
399 QMap< int, QMap< int, QVariant> > &colDataMap = d->dataMap[ index.column() ];
400 QMap< int, QVariant > &dataMap = colDataMap[ index.row() ];
401 dataMap.insert( role, value );
402 Q_EMIT attributesChanged( index, index );
403 return true;
404 }
405 }
406
resetData(const QModelIndex & index,int role)407 bool AttributesModel::resetData ( const QModelIndex & index, int role )
408 {
409 return setData( index, QVariant(), role );
410 }
411
setHeaderData(int section,Qt::Orientation orientation,const QVariant & value,int role)412 bool AttributesModel::setHeaderData ( int section, Qt::Orientation orientation,
413 const QVariant & value, int role )
414 {
415 if ( sourceModel() && headerData( section, orientation, role ) == value ) {
416 return true;
417 }
418
419 if ( !isKnownAttributesRole( role ) ) {
420 return sourceModel()->setHeaderData( section, orientation, value, role );
421 } else {
422 QMap< int, QMap<int, QVariant > > §ionDataMap
423 = orientation == Qt::Horizontal ? d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
424
425 QMap< int, QVariant > &dataMap = sectionDataMap[ section ];
426 dataMap.insert( role, value );
427 if ( sourceModel() ) {
428 int numRows = rowCount( QModelIndex() );
429 int numCols = columnCount( QModelIndex() );
430 if ( orientation == Qt::Horizontal && numRows > 0 )
431 Q_EMIT attributesChanged( index( 0, section, QModelIndex() ),
432 index( numRows - 1, section, QModelIndex() ) );
433 else if ( orientation == Qt::Vertical && numCols > 0 )
434 Q_EMIT attributesChanged( index( section, 0, QModelIndex() ),
435 index( section, numCols - 1, QModelIndex() ) );
436 Q_EMIT headerDataChanged( orientation, section, section );
437
438 // FIXME: This only makes sense for orientation == Qt::Horizontal,
439 // but what if orientation == Qt::Vertical?
440 if ( section != -1 && numRows > 0 )
441 Q_EMIT dataChanged( index( 0, section, QModelIndex() ),
442 index( numRows - 1, section, QModelIndex() ) );
443 }
444 return true;
445 }
446 }
447
resetHeaderData(int section,Qt::Orientation orientation,int role)448 bool AttributesModel::resetHeaderData ( int section, Qt::Orientation orientation, int role )
449 {
450 return setHeaderData ( section, orientation, QVariant(), role );
451 }
452
setPaletteType(AttributesModel::PaletteType type)453 void AttributesModel::setPaletteType( AttributesModel::PaletteType type )
454 {
455 if ( d->paletteType == type ) {
456 return;
457 }
458 d->paletteType = type;
459 switch ( type ) {
460 case PaletteTypeDefault:
461 d->palette = Palette::defaultPalette();
462 break;
463 case PaletteTypeSubdued:
464 d->palette = Palette::subduedPalette();
465 break;
466 case PaletteTypeRainbow:
467 d->palette = Palette::rainbowPalette();
468 break;
469 default:
470 qWarning( "Unknown palette type!" );
471 }
472 }
473
paletteType() const474 AttributesModel::PaletteType AttributesModel::paletteType() const
475 {
476 return d->paletteType;
477 }
478
setModelData(const QVariant value,int role)479 bool KChart::AttributesModel::setModelData( const QVariant value, int role )
480 {
481 d->modelDataMap.insert( role, value );
482 int numRows = rowCount( QModelIndex() );
483 int numCols = columnCount( QModelIndex() );
484 if ( sourceModel() && numRows > 0 && numCols > 0 ) {
485 Q_EMIT attributesChanged( index( 0, 0, QModelIndex() ),
486 index( numRows - 1, numCols - 1, QModelIndex() ) );
487 beginResetModel();
488 endResetModel();
489 }
490 return true;
491 }
492
modelData(int role) const493 QVariant KChart::AttributesModel::modelData( int role ) const
494 {
495 return d->modelDataMap.value( role, QVariant() );
496 }
497
rowCount(const QModelIndex & index) const498 int AttributesModel::rowCount( const QModelIndex& index ) const
499 {
500 if ( sourceModel() ) {
501 return sourceModel()->rowCount( mapToSource(index) );
502 } else {
503 return 0;
504 }
505 }
506
columnCount(const QModelIndex & index) const507 int AttributesModel::columnCount( const QModelIndex& index ) const
508 {
509 if ( sourceModel() ) {
510 return sourceModel()->columnCount( mapToSource(index) );
511 } else {
512 return 0;
513 }
514 }
515
setSourceModel(QAbstractItemModel * sourceModel)516 void AttributesModel::setSourceModel( QAbstractItemModel* sourceModel )
517 {
518 if ( this->sourceModel() != nullptr )
519 {
520 disconnect( this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
521 this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
522 disconnect( this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
523 this, SLOT(slotRowsInserted(QModelIndex,int,int)) );
524 disconnect( this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
525 this, SLOT(slotRowsRemoved(QModelIndex,int,int)) );
526 disconnect( this->sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
527 this, SLOT(slotRowsAboutToBeInserted(QModelIndex,int,int)) );
528 disconnect( this->sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
529 this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)) );
530 disconnect( this->sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
531 this, SLOT(slotColumnsInserted(QModelIndex,int,int)) );
532 disconnect( this->sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
533 this, SLOT(slotColumnsRemoved(QModelIndex,int,int)) );
534 disconnect( this->sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
535 this, SLOT(slotColumnsAboutToBeInserted(QModelIndex,int,int)) );
536 disconnect( this->sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
537 this, SLOT(slotColumnsAboutToBeRemoved(QModelIndex,int,int)) );
538 disconnect( this->sourceModel(), SIGNAL(modelReset()),
539 this, SIGNAL(modelReset()) );
540 disconnect( this->sourceModel(), SIGNAL(layoutChanged()),
541 this, SIGNAL(layoutChanged()) );
542 }
543 QAbstractProxyModel::setSourceModel( sourceModel );
544 if ( this->sourceModel() != nullptr )
545 {
546 connect( this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
547 this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
548 connect( this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
549 this, SLOT(slotRowsInserted(QModelIndex,int,int)) );
550 connect( this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
551 this, SLOT(slotRowsRemoved(QModelIndex,int,int)) );
552 connect( this->sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
553 this, SLOT(slotRowsAboutToBeInserted(QModelIndex,int,int)) );
554 connect( this->sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
555 this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)) );
556 connect( this->sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
557 this, SLOT(slotColumnsInserted(QModelIndex,int,int)) );
558 connect( this->sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
559 this, SLOT(slotColumnsRemoved(QModelIndex,int,int)) );
560 connect( this->sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
561 this, SLOT(slotColumnsAboutToBeInserted(QModelIndex,int,int)) );
562 connect( this->sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
563 this, SLOT(slotColumnsAboutToBeRemoved(QModelIndex,int,int)) );
564 connect( this->sourceModel(), SIGNAL(modelReset()),
565 this, SIGNAL(modelReset()) );
566 connect( this->sourceModel(), SIGNAL(layoutChanged()),
567 this, SIGNAL(layoutChanged()) );
568 }
569 }
570
slotRowsAboutToBeInserted(const QModelIndex & parent,int start,int end)571 void AttributesModel::slotRowsAboutToBeInserted( const QModelIndex& parent, int start, int end )
572 {
573 beginInsertRows( mapFromSource( parent ), start, end );
574 }
575
slotColumnsAboutToBeInserted(const QModelIndex & parent,int start,int end)576 void AttributesModel::slotColumnsAboutToBeInserted( const QModelIndex& parent, int start, int end )
577 {
578 beginInsertColumns( mapFromSource( parent ), start, end );
579 }
580
slotRowsInserted(const QModelIndex & parent,int start,int end)581 void AttributesModel::slotRowsInserted( const QModelIndex& parent, int start, int end )
582 {
583 Q_UNUSED( parent );
584 Q_UNUSED( start );
585 Q_UNUSED( end );
586 endInsertRows();
587 }
588
slotColumnsInserted(const QModelIndex & parent,int start,int end)589 void AttributesModel::slotColumnsInserted( const QModelIndex& parent, int start, int end )
590 {
591 Q_UNUSED( parent );
592 Q_UNUSED( start );
593 Q_UNUSED( end );
594 endInsertColumns();
595 }
596
slotRowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)597 void AttributesModel::slotRowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
598 {
599 beginRemoveRows( mapFromSource( parent ), start, end );
600 }
601
slotColumnsAboutToBeRemoved(const QModelIndex & parent,int start,int end)602 void AttributesModel::slotColumnsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
603 {
604 beginRemoveColumns( mapFromSource( parent ), start, end );
605 }
606
slotRowsRemoved(const QModelIndex & parent,int start,int end)607 void AttributesModel::slotRowsRemoved( const QModelIndex& parent, int start, int end )
608 {
609 Q_UNUSED( parent );
610 Q_UNUSED( start );
611 Q_UNUSED( end );
612 endRemoveRows();
613 }
614
removeEntriesFromDataMap(int start,int end)615 void AttributesModel::removeEntriesFromDataMap( int start, int end )
616 {
617 QMap< int, QMap< int, QMap< int, QVariant > > >::iterator it = d->dataMap.find( end );
618 // check that the element was found
619 if ( it != d->dataMap.end() ) {
620 ++it;
621 QVector< int > indexesToDel;
622 for ( int i = start; i < end && it != d->dataMap.end(); ++i ) {
623 d->dataMap[ i ] = it.value();
624 indexesToDel << it.key();
625 ++it;
626 }
627 if ( indexesToDel.isEmpty() ) {
628 for ( int i = start; i < end; ++i ) {
629 indexesToDel << i;
630 }
631 }
632 for ( int i = 0; i < indexesToDel.count(); ++i ) {
633 d->dataMap.remove( indexesToDel[ i ] );
634 }
635 }
636 }
637
removeEntriesFromDirectionDataMaps(Qt::Orientation dir,int start,int end)638 void AttributesModel::removeEntriesFromDirectionDataMaps( Qt::Orientation dir, int start, int end )
639 {
640 QMap<int, QMap<int, QVariant> > §ionDataMap
641 = dir == Qt::Horizontal ? d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
642 QMap<int, QMap<int, QVariant> >::iterator it = sectionDataMap.upperBound( end );
643 // check that the element was found
644 if ( it != sectionDataMap.end() )
645 {
646 QVector< int > indexesToDel;
647 for ( int i = start; i < end && it != sectionDataMap.end(); ++i )
648 {
649 sectionDataMap[ i ] = it.value();
650 indexesToDel << it.key();
651 ++it;
652 }
653 if ( indexesToDel.isEmpty() )
654 {
655 for ( int i = start; i < end; ++i )
656 {
657 indexesToDel << i;
658 }
659 }
660 for ( int i = 0; i < indexesToDel.count(); ++i )
661 {
662 sectionDataMap.remove( indexesToDel[ i ] );
663 }
664 }
665 }
666
slotColumnsRemoved(const QModelIndex & parent,int start,int end)667 void AttributesModel::slotColumnsRemoved( const QModelIndex& parent, int start, int end )
668 {
669 Q_UNUSED( parent );
670 Q_UNUSED( start );
671 Q_UNUSED( end );
672 Q_ASSERT_X( sourceModel(), "removeColumn", "This should only be triggered if a valid source Model exists!" );
673 for ( int i = start; i <= end; ++i ) {
674 d->verticalHeaderDataMap.remove( start );
675 }
676 removeEntriesFromDataMap( start, end );
677 removeEntriesFromDirectionDataMaps( Qt::Horizontal, start, end );
678 removeEntriesFromDirectionDataMaps( Qt::Vertical, start, end );
679
680 endRemoveColumns();
681 }
682
slotDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)683 void AttributesModel::slotDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight )
684 {
685 Q_EMIT dataChanged( mapFromSource( topLeft ), mapFromSource( bottomRight ) );
686 }
687
setDefaultForRole(int role,const QVariant & value)688 void AttributesModel::setDefaultForRole( int role, const QVariant& value )
689 {
690 if ( value.isValid() ) {
691 d->defaultsMap.insert( role, value );
692 } else {
693 // erase the possibily existing value to not let the map grow:
694 QMap<int, QVariant>::iterator it = d->defaultsMap.find( role );
695 if ( it != d->defaultsMap.end() ) {
696 d->defaultsMap.erase( it );
697 }
698 }
699
700 Q_ASSERT( defaultsForRole( role ).value<KChart::DataValueAttributes>() == value.value<KChart::DataValueAttributes>() );
701 }
702
setDatasetDimension(int dimension)703 void AttributesModel::setDatasetDimension( int dimension )
704 {
705 //### need to "reformat" or throw away internal data?
706 d->dataDimension = dimension;
707 }
708
datasetDimension() const709 int AttributesModel::datasetDimension() const
710 {
711 return d->dataDimension;
712 }
713