1 /* This file is part of the KDE project
2 
3    Copyright 2008 Johannes Simon <johannes.simon@gmail.com>
4    Copyright (C) 2010 Carlos Licea <carlos@kdab.com>
5    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6      Contact: Suresh Chande suresh.chande@nokia.com
7 
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public
10    License as published by the Free Software Foundation; either
11    version 2 of the License, or (at your option) any later version.
12 
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17 
18    You should have received a copy of the GNU Library General Public License
19    along with this library; see the file COPYING.LIB.  If not, write to
20    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.
22 */
23 
24 #ifndef KCHART_KDCHARTMODEL_H
25 #define KCHART_KDCHARTMODEL_H
26 
27 
28 // Qt
29 #include <QAbstractItemModel>
30 
31 // KoChart
32 #include "ChartShape.h"
33 
34 
35 namespace KoChart {
36 
37 class DataSet;
38 
39 /**
40  * Takes a list of DataSet's and compiles them into a
41  * QAbstractItemModel for use with KChart.
42  *
43  * Data sets in this model are aligned column-wise. Each column
44  * occupies dimension() columns. For example, for an X/Y chart,
45  * the data of this model would be structured as follows:
46  *
47  *             Brush 0       Brush 1
48  *             Pen 0         Pen 1
49  *             Label 0       Label 1
50  * -----------|------|------|------|------|
51  * Category 1 | x0,0 | y0,0 | x1,0 | x1,0 |
52  * -----------|------|------|------|------|
53  * Category 2 | x0,1 | y0,1 | x1,1 | x1,1 |
54  * -----------|------|------|------|------|
55  * Category 3 | x0,2 | y0,2 | x1,2 | x1,2 |
56  * -----------|------|------|------|------|
57  *
58  */
59 
60  /**
61   * Note on data directions in KChart's models:
62   *
63   * For circular (polar) charts, items shown in the legend should not be the
64   * data set labels, but the category labels instead. For example, a pie chart
65   * contains exactly one data set (if there's more series in the table, they are
66   * ignored). Obviously showing the title of the data set wouldn't be very useful
67   * in the legend. So the categories are shown instead.
68   *
69   * Since KChart extracts the legend items from horizontal header data (the headers
70   * in each column) data sets have to be inserted row-wise instead of column-wise for
71   * these charts. To do so, KChartModel::setDataDirection(Qt::Horizontal) is used.
72   *
73   * In all other cases, we show the data set labels in the legend. Therefore we insert
74   * data sets column-wise, which is done by calling setDataDirection(Qt::Vertical).
75   */
76 
77 class KChartModel : public QAbstractItemModel
78 {
79     Q_OBJECT
80 
81 public:
82     explicit KChartModel(PlotArea *plotArea, QObject *parent = 0);
83     ~KChartModel();
84 
85     enum DataRole {
86         XDataRole,
87         YDataRole,
88         ZDataRole,
89         LabelDataRole,
90         CategoryDataRole,
91         CustomDataRole,
92         BrushDataRole,
93         PenDataRole,
94         PieAttributesRole,
95         DataValueAttributesRole
96     };
97 
98     /**
99      * Specifies in what direction a data set 'points'. More specifically,
100      * if the data direction is Qt::Vertical, a data set occupies one
101      * column (in case only one data dimension is being used).
102      *
103      * See "Note on data directions in KChart's models" above.
104      */
105     void setDataDirection(Qt::Orientation direction);
106     /**
107      * See \a setDataDirection
108      */
109     Qt::Orientation dataDirection() const;
110     /**
111      * Returns the opposite of dataDirection().
112      */
113     Qt::Orientation categoryDirection() const;
114 
115 public Q_SLOTS:
116     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
117     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
118 
119     void slotColumnsInserted(const QModelIndex& parent, int start, int end);
120 
121     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
122     QModelIndex parent(const QModelIndex &index) const override;
123 
124     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
125     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
126 
127     void setDataDimensions(int dataDimensions);
128     int dataDimensions() const;
129 
130     void addDataSet(DataSet *dataSet);
131     void removeDataSet(DataSet *dataSet, bool silent = false);
132     QList<DataSet*> dataSets() const;
133 
134     /**
135      * Called by DataSet whenever a property that is global to all its data
136      * points changes, e.g. its label or its pen
137      */
138     void dataSetChanged(DataSet *dataSet);
139 
140     /**
141      * Called by DataSet whenever one or more of its data points changes,
142      * e.g. the x value of a data point.
143      *
144      * FIXME: @a role doesn't make sense here, it's not needed for emitting
145      *        the dataChanged() signal. Removing it would conflict with
146      *        dataSetChanged(DataSet*), that's why it's still there.
147      *
148      * @param first First data point that changed. If -1 it is assumed that
149      *              all data points in this series changed.
150      * @param last Last data point that changed. If -1 it is assumed that
151      *             only a single data point changed.
152      */
153     void dataSetChanged(DataSet *dataSet, DataRole role, int first = -1, int last = -1);
154 
155     /**
156      * Called by DataSet when the total number of data points it has changed.
157      */
158     void dataSetSizeChanged(DataSet *dataSet, int newSize);
159 
160 private:
161     class Private;
162     Private *const d;
163 };
164 
165 } // namespace KoChart
166 
167 #endif // KCHART_KDCHARTMODEL_H
168