KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
kdganttsummaryhandlingproxymodel.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Chart library.
4**
5** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
12#include "kdganttsummaryhandlingproxymodel_p.h"
13
14#include <QDebug>
15
16#include <cassert>
17
18using namespace KDGantt;
19
37
38bool SummaryHandlingProxyModel::Private::cacheLookup(const QModelIndex &idx,
39 QPair<QDateTime, QDateTime> *result) const
40{
41 // qDebug() << "cacheLookup("<<idx<<"), cache has " << cached_summary_items.count() << "items";
43 cached_summary_items.constFind(idx);
44 if (it != cached_summary_items.constEnd()) {
45 *result = *it;
46 return true;
47 } else {
48 return false;
49 }
50}
51
52void SummaryHandlingProxyModel::Private::insertInCache(const SummaryHandlingProxyModel *model,
53 const QModelIndex &sourceIdx) const
54{
55 QAbstractItemModel *sourceModel = model->sourceModel();
56 const QModelIndex &mainIdx = sourceIdx;
57 QDateTime st;
58 QDateTime et;
59
60 for (int r = 0; r < sourceModel->rowCount(mainIdx); ++r) {
61 QModelIndex pdIdx = model->mapFromSource(sourceModel->index(r, 0, mainIdx));
62 /* The probably results in recursive calls here */
63 QVariant tmpsv = model->data(pdIdx, StartTimeRole);
64 QVariant tmpev = model->data(pdIdx, EndTimeRole);
66 qDebug() << "Skipping item " << sourceIdx << " because it doesn't contain QDateTime";
67 continue;
68 }
69
70 // check for valid datetimes
71 if (tmpsv.type() == QVariant::DateTime && !tmpsv.value<QDateTime>().isValid())
72 continue;
73 if (tmpev.type() == QVariant::DateTime && !tmpev.value<QDateTime>().isValid())
74 continue;
75
76 // We need to test for empty strings to
77 // avoid a stupid Qt warning
78 if (tmpsv.type() == QVariant::String && tmpsv.value<QString>().isEmpty())
79 continue;
80 if (tmpev.type() == QVariant::String && tmpev.value<QString>().isEmpty())
81 continue;
82 QDateTime tmpst = tmpsv.toDateTime();
83 QDateTime tmpet = tmpev.toDateTime();
84 if (st.isNull() || st > tmpst)
85 st = tmpst;
86 if (et.isNull() || et < tmpet)
87 et = tmpet;
88 }
89 QVariant tmpssv = sourceModel->data(mainIdx, StartTimeRole);
90 QVariant tmpsev = sourceModel->data(mainIdx, EndTimeRole);
92 && !(tmpssv.canConvert(QVariant::String) && tmpssv.toString().isEmpty())
93 && tmpssv.toDateTime() != st)
94 sourceModel->setData(mainIdx, st, StartTimeRole);
96 && !(tmpsev.canConvert(QVariant::String) && tmpsev.toString().isEmpty())
97 && tmpsev.toDateTime() != et)
98 sourceModel->setData(mainIdx, et, EndTimeRole);
99 cached_summary_items[sourceIdx] = qMakePair(st, et);
100}
101
102void SummaryHandlingProxyModel::Private::removeFromCache(const QModelIndex &idx) const
103{
104 cached_summary_items.remove(idx);
105}
106
107void SummaryHandlingProxyModel::Private::clearCache() const
108{
109 cached_summary_items.clear();
110}
111
116 : BASE(parent)
117 , _d(new Private)
118{
119 init();
120}
121
122#define d d_func()
127
128void SummaryHandlingProxyModel::init()
129{
130}
131
132namespace {
133
134// Think this is ugly? Well, it's not from me, it comes from QProxyModel
135struct KDPrivateModelIndex
136{
137 int r, c;
138 void *p;
139 const QAbstractItemModel *m;
140};
141}
142
148{
150 d->clearCache();
151}
152
154{
155 d->clearCache();
156 BASE::sourceModelReset();
157}
158
160{
161 d->clearCache();
162 BASE::sourceLayoutChanged();
163}
164
166{
169 do {
171 if (model->data(dataIdx, ItemTypeRole) == TypeSummary) {
172 // qDebug() << "removing " << parentIdx << "from cache";
173 d->removeFromCache(dataIdx);
176 }
177 } while ((parentIdx = model->parent(parentIdx)) != QModelIndex());
178
179 BASE::sourceDataChanged(from, to);
180}
181
183 int start,
184 int end)
185{
186 BASE::sourceColumnsAboutToBeInserted(parentIdx, start, end);
187 d->clearCache();
188}
189
191 int start,
192 int end)
193{
194 BASE::sourceColumnsAboutToBeRemoved(parentIdx, start, end);
195 d->clearCache();
196}
197
199{
200 BASE::sourceRowsAboutToBeInserted(parentIdx, start, end);
201 d->clearCache();
202}
203
205{
206 BASE::sourceRowsAboutToBeRemoved(parentIdx, start, end);
207 d->clearCache();
208}
209
212{
214 const QAbstractItemModel *model = sourceModel();
215 Qt::ItemFlags f = model->flags(sidx);
216 if (d->isSummary(sidx)) {
217 f &= ~Qt::ItemIsEditable;
218 }
219 return f;
220}
221
223QVariant SummaryHandlingProxyModel::data(const QModelIndex &proxyIndex, int role) const
224{
225 // qDebug() << "SummaryHandlingProxyModel::data("<<proxyIndex<<role<<")";
227 const QAbstractItemModel *model = sourceModel();
228 if (d->isSummary(sidx) && (role == StartTimeRole || role == EndTimeRole)) {
229 // qDebug() << "requested summary";
231 if (d->cacheLookup(sidx, &result)) {
232 // qDebug() << "SummaryHandlingProxyModel::data(): Looking up summary for " << proxyIndex << role;
233 switch (role) {
234 case StartTimeRole:
235 return result.first;
236 case EndTimeRole:
237 return result.second;
238 default: /* fall thru */;
239 }
240 } else {
241 d->insertInCache(this, sidx);
242 return data(proxyIndex, role); /* TODO: Optimize */
243 }
244 }
245 return model->data(sidx, role);
246}
247
249bool SummaryHandlingProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
250{
252 if (role == StartTimeRole || role == EndTimeRole) {
254 do {
255 if (d->isSummary(parentIdx)) {
256 // qDebug() << "removing " << parentIdx << "from cache";
257 d->removeFromCache(parentIdx);
260 }
261 } while ((parentIdx = model->parent(parentIdx)) != QModelIndex());
262 }
263 return BASE::setData(index, value, role);
264}
265
266#undef d
267
268#ifndef KDAB_NO_UNIT_TESTS
269
270#include "unittest/test.h"
271
272#include <QStandardItemModel>
273
274static std::ostream &operator<<(std::ostream &os, const QDateTime &dt)
275{
276#ifdef QT_NO_STL
277 os << dt.toString().toLatin1().constData();
278#else
279 os << dt.toString().toStdString();
280#endif
281 return os;
282}
283
285{
287 QStandardItemModel sourceModel;
288
289 model.setSourceModel(&sourceModel);
290
291 auto *topitem = new QStandardItem(QString::fromLatin1("Summary"));
293 sourceModel.appendRow(topitem);
294
295 auto *task1 = new QStandardItem(QString::fromLatin1("Task1"));
297 auto *task2 = new QStandardItem(QString::fromLatin1("Task2"));
299 topitem->appendRow(task1);
300 topitem->appendRow(task2);
301
303 QDateTime enddt = startdt.addDays(1);
304
305 task1->setData(startdt, KDGantt::StartTimeRole);
306 task1->setData(enddt, KDGantt::EndTimeRole);
307 task2->setData(startdt, KDGantt::StartTimeRole);
308 task2->setData(enddt, KDGantt::EndTimeRole);
309
310 const QModelIndex topidx = model.index(0, 0, QModelIndex());
311
312 assertEqual(model.data(topidx, KDGantt::ItemTypeRole).toInt(), KDGantt::TypeSummary);
313 assertEqual(model.data(model.index(0, 0, topidx), KDGantt::ItemTypeRole).toInt(), KDGantt::TypeTask);
314
315 QDateTime task1startdt = model.data(model.index(0, 0, topidx), KDGantt::StartTimeRole).toDateTime();
316 assertEqual(task1startdt, startdt);
317
318 QDateTime summarystartdt = model.data(topidx, KDGantt::StartTimeRole).toDateTime();
319 assertEqual(summarystartdt, startdt);
320 assertTrue(model.flags(model.index(0, 0, topidx)) & Qt::ItemIsEditable);
321 assertFalse(model.flags(topidx) & Qt::ItemIsEditable);
322}
323
324#endif /* KDAB_NO_UNIT_TESTS */
325
326#include "moc_kdganttsummaryhandlingproxymodel.cpp"
QDebug operator<<(QDebug dbg, const KDChart::ThreeDBarAttributes &a)
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
Converts indexes in the source model to indexes in the proxy model.
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
Converts indexes in the proxy model to indexes in the source model.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Proxy model that supports summary gantt items.
Qt::ItemFlags flags(const QModelIndex &idx) const override
void sourceDataChanged(const QModelIndex &from, const QModelIndex &to) override
Called when the data in an existing item in the source model changes.
void sourceModelReset() override
Called when the source model is reset.
void sourceRowsAboutToBeInserted(const QModelIndex &idx, int start, int end) override
Called just before rows are inserted into the source model.
void sourceRowsAboutToBeRemoved(const QModelIndex &, int start, int end) override
Called just before rows are removed from the source model.
void sourceColumnsAboutToBeInserted(const QModelIndex &idx, int start, int end) override
Called just before columns are inserted into the source model.
void setSourceModel(QAbstractItemModel *model) override
Sets the model to be used as the source model for this proxy.
SummaryHandlingProxyModel(QObject *parent=nullptr)
Constructor.
void sourceLayoutChanged() override
Called when the layout of the source model has changed.
QVariant data(const QModelIndex &proxyIndex, int role=Qt::DisplayRole) const override
void sourceColumnsAboutToBeRemoved(const QModelIndex &idx, int start, int end) override
Called just before columns are removed from the source model.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
KDAB_SCOPED_UNITTEST_SIMPLE(KDGantt, Constraint, "test")
ForwardingProxyModel BASE
virtual QVariant data(const QModelIndex &index, int role) const const=0
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QModelIndex parent(const QModelIndex &index) const const=0
virtual int rowCount(const QModelIndex &parent) const const=0
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
virtual void setSourceModel(QAbstractItemModel *sourceModel)
const char * constData() const const
QDateTime addDays(qint64 ndays) const const
QDateTime currentDateTime()
bool isNull() const const
bool isValid() const const
QString toString(Qt::DateFormat format) const const
QHash::const_iterator constEnd() const const
QHash::const_iterator constFind(const Key &key) const const
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
void appendRow(const QList< QStandardItem * > &items)
QString fromLatin1(const char *str, int size)
bool isEmpty() const const
QByteArray toLatin1() const const
std::string toStdString() const const
typedef ItemFlags
bool canConvert(int targetTypeId) const const
QDateTime toDateTime() const const
int toInt(bool *ok) const const
QString toString() const const
QVariant::Type type() const const
T value() const const

© 2001 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-chart/
Generated on Fri Apr 26 2024 00:04:57 for KD Chart API Documentation by doxygen 1.9.8