1 /* This file is part of the Calligra project
2  * Copyright (c) 2008, 2012 Dag Andersen <danders@get2net.dk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 // clazy:excludeall=qstring-arg
21 #include "kptnodechartmodel.h"
22 
23 #include "kptlocale.h"
24 #include "kptnode.h"
25 #include "kptproject.h"
26 #include "kptschedule.h"
27 #include "kptresource.h"
28 #include "kptdebug.h"
29 
30 #include <KLocalizedString>
31 
32 #include <QVariant>
33 #include <QPen>
34 
35 #include <KChartGlobal>
36 #include <KChartPalette>
37 
38 
39 namespace KPlato
40 {
41 
ChartItemModel(QObject * parent)42 ChartItemModel::ChartItemModel(QObject *parent)
43     : ItemModelBase(parent),
44       m_localizeValues(false)
45 {
46 }
47 
parent(const QModelIndex & index) const48 QModelIndex ChartItemModel::parent(const QModelIndex &index) const
49 {
50     Q_UNUSED(index);
51     return QModelIndex();
52 }
53 
columnMap() const54 const QMetaEnum ChartItemModel::columnMap() const
55 {
56     return metaObject()->enumerator(metaObject()->indexOfEnumerator("Properties"));
57 }
58 
columnCount(const QModelIndex &) const59 int ChartItemModel::columnCount(const QModelIndex &/*parent*/) const
60 {
61     return columnMap().keyCount();
62 }
63 
rowCount(const QModelIndex & parent) const64 int ChartItemModel::rowCount(const QModelIndex &parent) const
65 {
66     if (parent.isValid()) {
67         return 0;
68     }
69     const QDate start = startDate();
70     const QDate end = endDate();
71     if (!start.isValid() || !end.isValid()) {
72         return 0;
73     }
74     return start.daysTo(end) + 1;
75 }
76 
index(int row,int column,const QModelIndex & parent) const77 QModelIndex ChartItemModel::index(int row, int column, const QModelIndex &parent) const
78 {
79     if (parent.isValid()) {
80         return QModelIndex();
81     }
82     if (m_project == nullptr || row < 0 || column < 0) {
83         //debugPlan<<"No project"<<m_project<<" or illegal row, column"<<row<<column;
84         return QModelIndex();
85     }
86     if (row >= rowCount()) {
87         return QModelIndex();
88     }
89     QModelIndex i = createIndex(row, column);
90     return i;
91 }
92 
bcwsEffort(int day) const93 double ChartItemModel::bcwsEffort(int day) const
94 {
95     const QDate date = startDate().addDays(day);
96     double v = m_bcws.hoursTo(date);
97     return v;
98 }
99 
bcwpEffort(int day) const100 double ChartItemModel::bcwpEffort(int day) const
101 {
102     double res = 0.0;
103     QDate date = startDate().addDays(day);
104     if (m_bcws.days().contains(date)) {
105         res = m_bcws.bcwpEffort(date);
106     } else if (date > m_bcws.endDate()) {
107         res = m_bcws.bcwpEffort(date);
108     }
109     return res;
110 }
111 
acwpEffort(int day) const112 double ChartItemModel::acwpEffort(int day) const
113 {
114     return m_acwp.hoursTo(startDate().addDays(day));
115 }
116 
bcwsCost(int day) const117 double ChartItemModel::bcwsCost(int day) const
118 {
119     return m_bcws.costTo(startDate().addDays(day));
120 }
121 
bcwpCost(int day) const122 double ChartItemModel::bcwpCost(int day) const
123 {
124     double res = 0.0;
125     QDate date = startDate().addDays(day);
126     if (m_bcws.days().contains(date)) {
127         res = m_bcws.bcwpCost(date);
128     } else if (date > m_bcws.endDate()) {
129         res = m_bcws.bcwpCost(m_bcws.endDate());
130     }
131     return res;
132 }
133 
acwpCost(int day) const134 double ChartItemModel::acwpCost(int day) const
135 {
136     return m_acwp.costTo(startDate().addDays(day));
137 }
138 
spiEffort(int day) const139 double ChartItemModel::spiEffort(int day) const
140 {
141     double p = bcwpEffort(day);
142     double s = bcwsEffort(day);
143     return s == 0.0 ? 0.0 : p / s;
144 }
145 
spiCost(int day) const146 double ChartItemModel::spiCost(int day) const
147 {
148     double p = bcwpCost(day);
149     double s = bcwsCost(day);
150     return s == 0.0 ? 0.0 : p / s;
151 }
152 
cpiEffort(int day) const153 double ChartItemModel::cpiEffort(int day) const
154 {
155     double p = bcwpEffort(day);
156     double a = acwpEffort(day);
157     return a == 0.0 ? 0.0 : p / a;
158 }
159 
cpiCost(int day) const160 double ChartItemModel::cpiCost(int day) const
161 {
162     double p = bcwpCost(day);
163     double a = acwpCost(day);
164     return a == 0.0 ? 0.0 : p / a;
165 }
166 
data(const QModelIndex & index,int role) const167 QVariant ChartItemModel::data(const QModelIndex &index, int role) const
168 {
169     QVariant result;
170     if (role == Qt::DisplayRole) {
171         if (! m_localizeValues) {
172             return data(index, Qt::EditRole);
173         } else {
174             QLocale locale;
175             // TODO: temporary workaround while KLocale/money logic still used
176             Locale *planLocale;
177             Locale *tmpPlanLocale = 0;
178             if (project()) {
179                 planLocale = project()->locale();
180             } else {
181                 tmpPlanLocale = new Locale();
182                 planLocale = tmpPlanLocale;
183             }
184             switch (index.column()) {
185             case BCWSCost: result = planLocale->formatMoney(bcwsCost(index.row()), QString(), 0); break;
186             case BCWPCost: result = planLocale->formatMoney(bcwpCost(index.row()), QString(), 0); break;
187             case ACWPCost: result = planLocale->formatMoney(acwpCost(index.row()), QString(), 0); break;
188             case BCWSEffort: result = locale.toString(bcwsEffort(index.row()), 'f', 1); break;
189             case BCWPEffort: result = locale.toString(bcwpEffort(index.row()), 'f', 1); break;
190             case ACWPEffort: result = locale.toString(acwpEffort(index.row()), 'f', 1); break;
191             case SPICost: result = locale.toString(spiCost(index.row()), 'f', 2); break;
192             case CPICost: result = locale.toString(cpiCost(index.row()), 'f', 2); break;
193             case SPIEffort: result = locale.toString(spiEffort(index.row()), 'f', 2); break;
194             case CPIEffort: result = locale.toString(cpiEffort(index.row()), 'f', 2); break;
195             default: break;
196             }
197             delete tmpPlanLocale;
198         }
199         //debugPlan<<index<<role<<result;
200         return result;
201     } else if (role == Qt::EditRole) {
202         switch (index.column()) {
203         case BCWSCost: result = bcwsCost(index.row()); break;
204         case BCWPCost: result = bcwpCost(index.row()); break;
205         case ACWPCost: result = acwpCost(index.row()); break;
206         case BCWSEffort: result = bcwsEffort(index.row()); break;
207         case BCWPEffort: result = bcwpEffort(index.row()); break;
208         case ACWPEffort: result = acwpEffort(index.row()); break;
209         case SPICost: result = spiCost(index.row()); break;
210         case CPICost: result = cpiCost(index.row()); break;
211         case SPIEffort: result = spiEffort(index.row()); break;
212         case CPIEffort: result = cpiEffort(index.row()); break;
213         default: break;
214         }
215         //debugPlan<<index<<role<<result;
216         return result;
217     } else if (role == Qt::ForegroundRole) {
218         double v = 0.0;
219         switch (index.column()) {
220         case SPICost: v = spiCost(index.row()); break;
221         case CPICost: v = cpiCost(index.row()); break;
222         case SPIEffort: v = spiEffort(index.row()); break;
223         case CPIEffort: v = cpiEffort(index.row()); break;
224         default: break;
225         }
226         if (v > 0.0 && v < 1.0) {
227             result = QBrush(Qt::red);
228         }
229         return result;
230     }  else if (role == KChart::DatasetBrushRole) {
231         return headerData(index.column(), Qt::Horizontal, role);
232     }  else if (role == KChart::DatasetPenRole) {
233         return headerData(index.column(), Qt::Horizontal, role);
234     }
235     //debugPlan<<index<<role<<result;
236     return result;
237 }
238 
headerData(int section,Qt::Orientation orientation,int role) const239 QVariant ChartItemModel::headerData(int section, Qt::Orientation orientation, int role) const
240 {
241     QVariant result;
242     if (role == Qt::DisplayRole) {
243         if (orientation == Qt::Horizontal) {
244             switch (section) {
245                 case BCWSCost: return i18nc("Cost based Budgeted Cost of Work Scheduled", "BCWS Cost");
246                 case BCWPCost: return i18nc("Cost based Budgeted Cost of Work Performed", "BCWP Cost");
247                 case ACWPCost: return i18nc("Cost based Actual Cost of Work Performed", "ACWP Cost");
248                 case BCWSEffort: return i18nc("Effort based Budgeted Cost of Work Scheduled", "BCWS Effort");
249                 case BCWPEffort: return i18nc("Effort based Budgeted Cost of Work Performed", "BCWP Effort");
250                 case ACWPEffort: return i18nc("Effort based Actual Cost of Work Performed", "ACWP Effort");
251                 case SPICost: return i18nc("Cost based Schedule Performance Index", "SPI Cost");
252                 case CPICost: return i18nc("Cost based Cost Performance Index", "CPI Cost");
253                 case SPIEffort: return i18nc("Effort based Schedule Performance Index", "SPI Effort");
254                 case CPIEffort: return i18nc("Effort based Cost Performance Index", "CPI Effort");
255                 default: return QVariant();
256             }
257         } else {
258             return startDate().addDays(section).toString(i18nc("Date format used as chart axis labels. Must follow QDate specification.", "MM.dd"));
259         }
260     } else if (role == Qt::ToolTipRole) {
261         if (orientation == Qt::Horizontal) {
262             switch (section) {
263                 case BCWSCost: return xi18nc("@info:tooltip", "Cost based Budgeted Cost of Work Scheduled");
264                 case BCWPCost: return xi18nc("@info:tooltip", "Cost based Budgeted Cost of Work Performed");
265                 case ACWPCost: return xi18nc("@info:tooltip", "Cost based Actual Cost of Work Performed");
266                 case BCWSEffort: return xi18nc("@info:tooltip", "Effort based Budgeted Cost of Work Scheduled");
267                 case BCWPEffort: return xi18nc("@info:tooltip", "Effort based Budgeted Cost of Work Performed");
268                 case ACWPEffort: return xi18nc("@info:tooltip", "Effort based Actual Cost of Work Performed");
269                 case SPICost: return xi18nc("@info:tooltip", "Cost based Schedule Performance Index (BCWP/BCWS)");
270                 case CPICost: return xi18nc("@info:tooltip", "Cost based Cost Performance Index (BCWP/ACWS)");
271                 case SPIEffort: return xi18nc("@info:tooltip", "Effort based Schedule Performance Index (BCWP/BCWS)");
272                 case CPIEffort: return xi18nc("@info:tooltip", "Effort based Cost Performance Index (BCWP/ACWS)");
273                 default: return QVariant();
274             }
275         } else {
276             return QLocale().toString(startDate().addDays(section), QLocale::ShortFormat);
277         }
278     } else if (role == Qt::EditRole) {
279         if (orientation == Qt::Horizontal) {
280             switch (section) {
281                 case BCWSCost: return "BCWS Cost";
282                 case BCWPCost: return "BCWP Cost";
283                 case ACWPCost: return "ACWP Cost";
284                 case BCWSEffort: return "BCWS Effort";
285                 case BCWPEffort: return "BCWP Effort";
286                 case ACWPEffort: return "ACWP Effort";
287                 case SPICost: return "SPI Cost";
288                 case CPICost: return "CPI Cost";
289                 case SPIEffort: return "SPI Effort";
290                 case CPIEffort: return "CPI Effort";
291                 default: return QVariant();
292             }
293         } else {
294             return startDate().addDays(section);
295         }
296 #ifdef PLAN_CHART_DEBUG
297     } else if (role == Qt::BackgroundRole) {
298         if (orientation == Qt::Vertical) {
299             if (startDate().addDays(section) == QDate::currentDate()) {
300                 return QBrush(Qt::red);
301             }
302         }
303 #endif
304     }  else if (role == KChart::DatasetBrushRole) {
305         if (orientation == Qt::Horizontal) {
306             return KChart::Palette::defaultPalette().getBrush(section);
307         }
308     }  else if (role == KChart::DatasetPenRole) {
309         QPen p;
310         p.setBrush(headerData(section, orientation, KChart::DatasetBrushRole).value<QBrush>());
311         result = p;
312         //debugPlan<<section<<"DatasetPenRole"<<result;
313         return result;
314     }
315     return ItemModelBase::headerData(section, orientation, role);
316 }
317 
setProject(Project * project)318 void ChartItemModel::setProject(Project *project)
319 {
320     beginResetModel();
321     m_bcws.clear();
322     m_acwp.clear();
323     if (m_project) {
324         disconnect(m_project, &Project::aboutToBeDeleted, this, &ChartItemModel::projectDeleted);
325         disconnect(m_project, &Project::projectCalculated, this, &ChartItemModel::slotSetScheduleManager);
326         disconnect(m_project, &Project::nodeRemoved, this, &ChartItemModel::slotNodeRemoved);
327         disconnect(m_project, &Project::nodeChanged, this, &ChartItemModel::slotNodeChanged);
328         disconnect(m_project, &Project::resourceRemoved, this, &ChartItemModel::slotResourceRemoved);
329         disconnect(m_project, &Project::resourceChanged, this, &ChartItemModel::slotResourceChanged);
330     }
331     m_project = project;
332     if (m_project) {
333         connect(m_project, &Project::aboutToBeDeleted, this, &ChartItemModel::projectDeleted);
334         connect(m_project, &Project::projectCalculated, this, &ChartItemModel::slotSetScheduleManager);
335         connect(m_project, &Project::nodeRemoved, this, &ChartItemModel::slotNodeRemoved);
336         connect(m_project, &Project::nodeChanged, this, &ChartItemModel::slotNodeChanged);
337         connect(m_project, &Project::resourceRemoved, this, &ChartItemModel::slotResourceRemoved);
338         connect(m_project, &Project::resourceChanged, this, &ChartItemModel::slotResourceChanged);
339     }
340     endResetModel();
341 }
342 
slotSetScheduleManager(ScheduleManager * sm)343 void ChartItemModel::slotSetScheduleManager(ScheduleManager *sm)
344 {
345     setScheduleManager(sm);
346 }
347 
setScheduleManager(ScheduleManager * sm)348 void ChartItemModel::setScheduleManager(ScheduleManager *sm)
349 {
350     beginResetModel();
351     m_manager = sm;
352     calculate();
353     endResetModel();
354 }
355 
setNodes(const QList<Node * > & nodes)356 void ChartItemModel::setNodes(const QList<Node*> &nodes)
357 {
358     beginResetModel();
359     debugPlan<<nodes;
360     m_nodes = nodes;
361     calculate();
362     endResetModel();
363 }
364 
addNode(Node * node)365 void ChartItemModel::addNode(Node *node)
366 {
367     beginResetModel();
368     m_nodes.append(node);
369     calculate();
370     endResetModel();
371 }
372 
clearNodes()373 void ChartItemModel::clearNodes()
374 {
375     beginResetModel();
376     m_nodes.clear();
377     calculate();
378     endResetModel();
379 }
380 
slotNodeRemoved(Node * node)381 void ChartItemModel::slotNodeRemoved(Node *node)
382 {
383     if (m_nodes.contains(node)) {
384         beginResetModel();
385         m_nodes.removeAt(m_nodes.indexOf(node));
386         calculate();
387         endResetModel();
388     }
389 }
390 
slotNodeChanged(Node * node)391 void ChartItemModel::slotNodeChanged(Node *node)
392 {
393     //debugPlan<<this<<node;
394     if (m_nodes.contains(node)) {
395         beginResetModel();
396         calculate();
397         endResetModel();
398         return;
399     }
400     foreach (Node *n, m_nodes) {
401         if (node->isChildOf(n)) {
402             beginResetModel();
403             calculate();
404             endResetModel();
405             return;
406         }
407     }
408 }
409 
slotResourceChanged(Resource *)410 void ChartItemModel::slotResourceChanged(Resource*)
411 {
412     beginResetModel();
413     calculate();
414     endResetModel();
415 }
416 
slotResourceRemoved(const Resource *)417 void ChartItemModel::slotResourceRemoved(const Resource*)
418 {
419     beginResetModel();
420     calculate();
421     endResetModel();
422 }
423 
startDate() const424 QDate ChartItemModel::startDate() const
425 {
426     QDate d = m_bcws.startDate();
427     if (m_acwp.startDate().isValid()) {
428         if (! d.isValid() || d > m_acwp.startDate()) {
429             d = m_acwp.startDate();
430         }
431     }
432     return d;
433 }
434 
endDate() const435 QDate ChartItemModel::endDate() const
436 {
437     return qMax(m_bcws.endDate(), m_acwp.endDate());
438 }
439 
calculate()440 void ChartItemModel::calculate()
441 {
442     //debugPlan<<this<<m_project<<m_manager<<m_nodes;
443     m_bcws.clear();
444     m_acwp.clear();
445     if (m_manager) {
446         if (m_project) {
447             foreach (Node *n, m_nodes) {
448                 bool skip = false;
449                 foreach (Node *p, m_nodes) {
450                     if (n->isChildOf(p)) {
451                         skip = true;
452                         break;
453                     }
454                 }
455                 if (! skip) {
456                     m_bcws += n->bcwpPrDay(m_manager->scheduleId(), ECCT_EffortWork);
457                     m_acwp += n->acwp(m_manager->scheduleId());
458                 }
459             }
460         }
461     }
462     //debugPlan<<"bcwp"<<m_bcws;
463     //debugPlan<<"acwp"<<m_acwp;
464 }
465 
setLocalizeValues(bool on)466 void ChartItemModel::setLocalizeValues(bool on)
467 {
468     m_localizeValues = on;
469 }
470 
rowForDate(const QDate & date) const471 int ChartItemModel::rowForDate(const QDate &date) const
472 {
473     return std::min(rowCount()-1, static_cast<int>(startDate().daysTo(date)));
474 }
475 
476 //-------------------------
PerformanceDataCurrentDateModel(QObject * parent)477 PerformanceDataCurrentDateModel::PerformanceDataCurrentDateModel(QObject *parent)
478     : QAbstractProxyModel(parent)
479 {
480     ChartItemModel *m = new ChartItemModel(this);
481     m->setLocalizeValues(true);
482     setSourceModel(m);
483 }
484 
485 
rowCount(const QModelIndex & parent) const486 int PerformanceDataCurrentDateModel::rowCount(const QModelIndex &parent) const
487 {
488     if (parent.isValid()) {
489         return 0;
490     }
491     return 2;
492 }
493 
columnCount(const QModelIndex &) const494 int PerformanceDataCurrentDateModel::columnCount(const QModelIndex &/*parent*/) const
495 {
496     return 5;
497 }
498 
parent(const QModelIndex & idx) const499 QModelIndex PerformanceDataCurrentDateModel::parent(const QModelIndex &idx) const
500 {
501     return QModelIndex();
502 }
503 
index(int row,int column,const QModelIndex & parent) const504 QModelIndex PerformanceDataCurrentDateModel::index(int row, int column, const QModelIndex &parent) const
505 {
506     if (parent.isValid()) {
507         return QModelIndex();
508     }
509     return createIndex(row, column);
510 }
511 
data(const QModelIndex & idx,int role) const512 QVariant PerformanceDataCurrentDateModel::data(const QModelIndex &idx, int role) const
513 {
514     const QModelIndex i = mapToSource(idx);
515     QVariant v = sourceModel()->data(i, role);
516     return v;
517 }
518 
headerData(int section,Qt::Orientation o,int role) const519 QVariant PerformanceDataCurrentDateModel::headerData(int section, Qt::Orientation o, int role) const
520 {
521     if (role == Qt::DisplayRole) {
522         if (o == Qt::Horizontal) {
523             switch (section) {
524             case 0: return xi18nc("@title:column Budgeted Cost of Work Scheduled", "BCWS");
525             case 1: return xi18nc("@title:column Budgeted Cost of Work Performed", "BCWP");
526             case 2: return xi18nc("@title:column Actual Cost of Work Performed", "ACWP");
527             case 3: return xi18nc("@title:column Schedule Performance Index", "SPI");
528             case 4: return xi18nc("@title:column Cost Performance Index", "CPI");
529             default: break;
530             }
531         } else {
532             switch (section) {
533             case 0: return xi18nc("@title:column", "Cost:");
534             case 1: return xi18nc("@title:column", "Effort:");
535             default: break;
536             }
537         }
538     } else if (role == Qt::ToolTipRole) {
539         if (o == Qt::Horizontal) {
540             switch (section) {
541             case 0: return xi18nc("@info:tooltip", "Budgeted Cost of Work Scheduled");
542             case 1: return xi18nc("@info:tooltip", "Budgeted Cost of Work Performed");
543             case 2: return xi18nc("@info:tooltip", "Actual Cost of Work Performed");
544             case 3: return xi18nc("@info:tooltip", "Schedule Performance Index");
545             case 4: return xi18nc("@info:tooltip", "Cost Performance Index");
546             default: break;
547             }
548         } else {
549             switch (section) {
550             case 0: return xi18nc("@info:tooltip", "Performance indicators based on cost");
551             case 1: return xi18nc("@info:tooltip", "Performance indicators based on effort");
552             default: break;
553             }
554         }
555     }
556     return QVariant();
557 }
558 
mapToSource(const QModelIndex & idx) const559 QModelIndex PerformanceDataCurrentDateModel::mapToSource(const QModelIndex &idx) const
560 {
561     if (! startDate().isValid() || sourceModel()->rowCount() == 0) {
562         return QModelIndex();
563     }
564     int row = qobject_cast<ChartItemModel*>(sourceModel())->rowForDate(QDate::currentDate());
565     if (row < 0) {
566         return QModelIndex();
567     }
568     int column = -1;
569     switch (idx.column()) {
570         case 0: column = idx.row() == 0 ? ChartItemModel::BCWSCost : ChartItemModel::BCWSEffort; break; // BCWS
571         case 1: column = idx.row() == 0 ? ChartItemModel::BCWPCost : ChartItemModel::BCWPEffort; break; // BCWP
572         case 2: column = idx.row() == 0 ? ChartItemModel::ACWPCost : ChartItemModel::ACWPEffort; break; // ACWP
573         case 3: column = idx.row() == 0 ? ChartItemModel::SPICost : ChartItemModel::SPIEffort; break; // SPI
574         case 4: column = idx.row() == 0 ? ChartItemModel::CPICost : ChartItemModel::CPIEffort; break; // CPI
575         default: break;
576     }
577     if (column < 0) {
578         return QModelIndex();
579     }
580     const QModelIndex i = sourceModel()->index(row, column);
581     return i;
582 }
583 
mapFromSource(const QModelIndex & sourceIndex) const584 QModelIndex PerformanceDataCurrentDateModel::mapFromSource(const QModelIndex &sourceIndex) const
585 {
586     int col = sourceIndex.column();
587     int row = 0;
588     if (col > columnCount()) {
589         col -= columnCount();
590         row = 1;
591     }
592     return createIndex(row, col);
593 }
594 
startDate() const595 QDate PerformanceDataCurrentDateModel::startDate() const
596 {
597     return qobject_cast<ChartItemModel*>(sourceModel())->startDate();
598 }
599 
endDate() const600 QDate PerformanceDataCurrentDateModel::endDate() const
601 {
602     return qobject_cast<ChartItemModel*>(sourceModel())->endDate();
603 }
604 
project() const605 Project *PerformanceDataCurrentDateModel::project() const
606 {
607     return qobject_cast<ChartItemModel*>(sourceModel())->project();
608 }
609 
scheduleManager() const610 ScheduleManager *PerformanceDataCurrentDateModel::scheduleManager() const
611 {
612     return qobject_cast<ChartItemModel*>(sourceModel())->scheduleManager();
613 }
614 
isReadWrite() const615 bool PerformanceDataCurrentDateModel::isReadWrite() const
616 {
617     return qobject_cast<ChartItemModel*>(sourceModel())->isReadWrite();
618 }
619 
setNodes(const QList<Node * > & nodes)620 void PerformanceDataCurrentDateModel::setNodes(const QList<Node*> &nodes)
621 {
622     qobject_cast<ChartItemModel*>(sourceModel())->setNodes(nodes);
623 }
624 
addNode(Node * node)625 void PerformanceDataCurrentDateModel::addNode(Node *node)
626 {
627     qobject_cast<ChartItemModel*>(sourceModel())->addNode(node);
628 }
629 
clearNodes()630 void PerformanceDataCurrentDateModel::clearNodes()
631 {
632     qobject_cast<ChartItemModel*>(sourceModel())->clearNodes();
633 }
634 
setProject(KPlato::Project * project)635 void PerformanceDataCurrentDateModel::setProject(KPlato::Project *project)
636 {
637     qobject_cast<ChartItemModel*>(sourceModel())->setProject(project);
638 }
639 
setScheduleManager(KPlato::ScheduleManager * sm)640 void PerformanceDataCurrentDateModel::setScheduleManager(KPlato::ScheduleManager *sm)
641 {
642     qobject_cast<ChartItemModel*>(sourceModel())->setScheduleManager(sm);
643 }
644 
setReadWrite(bool rw)645 void PerformanceDataCurrentDateModel::setReadWrite(bool rw)
646 {
647     qobject_cast<ChartItemModel*>(sourceModel())->setReadWrite(rw);
648 }
649 
650 } //namespace KPlato
651