1/* This file is part of the KDE project
2 Copyright (C) 2007, 2012 Dag Andersen <danders@get2net>
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#include "kptpertcpmmodel.h"
21
22#include "kptglobal.h"
23#include "kptcommonstrings.h"
24#include "kptproject.h"
25#include "kpttask.h"
26#include "kptnode.h"
27#include "kptschedule.h"
28#include "kptdebug.h"
29
30#include <QStringList>
31#include <QMimeData>
32
33#include <kglobal.h>
34#include <klocale.h>
35
36
37namespace KPlato
38{
39
40class Project;
41class Node;
42class Task;
43
44typedef QList<Node*> NodeList;
45
46CriticalPathItemModel::CriticalPathItemModel( QObject *parent )
47 : ItemModelBase( parent ),
48 m_manager( 0 )
49{
50/* connect( this, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()) );
51 connect( this, SIGNAL(modelReset()), SLOT(slotReset()) );*/
52}
53
54CriticalPathItemModel::~CriticalPathItemModel()
55{
56}
57
58void CriticalPathItemModel::slotNodeToBeInserted( Node *, int )
59{
60 //kDebug(planDbg())<<node->name();
61}
62
63void CriticalPathItemModel::slotNodeInserted( Node * /*node*/ )
64{
65 //kDebug(planDbg())<<node->getParent->name()<<"-->"<<node->name();
66}
67
68void CriticalPathItemModel::slotNodeToBeRemoved( Node *node )
69{
70 Q_UNUSED(node);
71 //kDebug(planDbg())<<node->name();
72/* if ( m_path.contains( node ) ) {
73 }*/
74}
75
76void CriticalPathItemModel::slotNodeRemoved( Node *node )
77{
78 Q_UNUSED(node);
79 //kDebug(planDbg())<<node->name();
80}
81
82void CriticalPathItemModel::setProject( Project *project )
83{
84 if ( m_project ) {
85 disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) );
86 disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) );
87 disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) );
88 disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) );
89
90 disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) );
91 disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) );
92 disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) );
93 }
94 m_project = project;
95 m_nodemodel.setProject( project );
96 if ( project ) {
97 connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) );
98 connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) );
99 connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) );
100 connect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) );
101
102 connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) );
103 connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) );
104 connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) );
105 }
106 reset();
107}
108
109void CriticalPathItemModel::setManager( ScheduleManager *sm )
110{
111 kDebug(planDbg())<<this;
112 m_manager = sm;
113 m_nodemodel.setManager( sm );
114 if ( m_project == 0 || m_manager == 0 ) {
115 m_path.clear();
116 } else {
117 m_path = m_project->criticalPath( m_manager->scheduleId(), 0 );
118 }
119 kDebug(planDbg())<<m_path;
120 reset();
121}
122
123QModelIndex CriticalPathItemModel::parent( const QModelIndex & ) const
124{
125 return QModelIndex();
126}
127
128QModelIndex CriticalPathItemModel::index( int row, int column, const QModelIndex &parent ) const
129{
130 if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) {
131 return QModelIndex();
132 }
133 if ( parent.isValid() ) {
134 return QModelIndex();
135 }
136 Node *n = m_path.value( row );
137 QModelIndex i = createIndex(row, column, n );
138 return i;
139}
140
141Duration::Unit CriticalPathItemModel::presentationUnit( const Duration &dur ) const
142{
143 if ( dur.toDouble( Duration::Unit_d ) < 1.0 ) {
144 return Duration::Unit_h;
145 }
146 return Duration::Unit_d;
147}
148
149QVariant CriticalPathItemModel::name( int role ) const
150{
151 switch ( role ) {
152 case Qt::DisplayRole:
153 return i18n( "Path" );
154 case Qt::ToolTipRole:
155 case Qt::EditRole:
156 case Qt::StatusTipRole:
157 case Qt::WhatsThisRole:
158 return QVariant();
159 }
160 return QVariant();
161}
162
163QVariant CriticalPathItemModel::duration( int role ) const
164{
165 switch ( role ) {
166 case Qt::DisplayRole:
167 case Qt::ToolTipRole: {
168 Duration v = m_project->duration( m_manager->scheduleId() );
169 return QVariant(KGlobal::locale()->formatNumber( v.toDouble( presentationUnit( v ) ), 1 ) + Duration::unitToString( presentationUnit( v ) ));
170 }
171 case Qt::StatusTipRole:
172 case Qt::WhatsThisRole:
173 return QVariant();
174 }
175 return QVariant();
176}
177
178QVariant CriticalPathItemModel::variance( int role ) const
179{
180 switch ( role ) {
181 case Qt::DisplayRole:
182 case Qt::ToolTipRole: {
183 double v = 0.0;
184 foreach ( Node *n, m_path ) {
185 long id = m_manager->scheduleId();
186 v += n->variance( id, presentationUnit( m_project->duration( id ) ) );
187 }
188 return KGlobal::locale()->formatNumber( v, 1 );
189 break;
190 }
191 case Qt::EditRole: {
192 double v = 0.0;
193 foreach ( Node *n, m_path ) {
194 v += n->variance( m_manager->scheduleId() );
195 }
196 return v;
197 }
198 case Qt::StatusTipRole:
199 case Qt::WhatsThisRole:
200 return QVariant();
201 }
202 return QVariant();
203}
204
205QVariant CriticalPathItemModel::notUsed( int role ) const
206{
207 switch ( role ) {
208 case Qt::DisplayRole:
209 return "";
210 default:
211 return QVariant();
212 }
213 return QVariant();
214}
215
216QVariant CriticalPathItemModel::data( const QModelIndex &index, int role ) const
217{
218 QVariant result;
219 if ( ! index.isValid() ) {
220 return result;
221 }
222 if ( role == Qt::TextAlignmentRole ) {
223 return alignment( index.column() );
224 }
225 Node *n = node( index );
226 if ( n == 0 ) {
227 switch ( index.column() ) {
228 case NodeModel::NodeName: result = name( role ); break;
229 case NodeModel::NodeDuration: result = duration( role ); break;
230 case NodeModel::NodeVarianceDuration: result = variance( role ); break;
231 default:
232 result = notUsed( role ); break;
233 }
234 } else {
235 result = m_nodemodel.data( n, index.column(), role );
236 }
237 if ( result.isValid() ) {
238 if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) {
239 // HACK to show focus in empty cells
240 result = ' ';
241 }
242 return result;
243 }
244 return result;
245}
246
247QVariant CriticalPathItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
248{
249 if ( orientation == Qt::Horizontal ) {
250 if ( role == Qt::DisplayRole ) {
251 return m_nodemodel.headerData( section, role );
252 } else if ( role == Qt::TextAlignmentRole ) {
253 return alignment( section );
254 }
255 }
256 if ( role == Qt::ToolTipRole ) {
257 return m_nodemodel.headerData( section, role );
258 } else if ( role == Qt::WhatsThisRole ) {
259 return m_nodemodel.headerData( section, role );
260 }
261 return ItemModelBase::headerData(section, orientation, role);
262}
263
264QVariant CriticalPathItemModel::alignment( int column ) const
265{
266 return m_nodemodel.headerData( column, Qt::TextAlignmentRole );
267}
268
269int CriticalPathItemModel::columnCount( const QModelIndex & ) const
270{
271 return m_nodemodel.propertyCount();
272}
273
274int CriticalPathItemModel::rowCount( const QModelIndex &parent ) const
275{
276 if ( parent.isValid() ) {
277 return 0;
278 }
279 if ( m_manager && m_manager->expected() && m_manager->expected()->criticalPathList() ) {
280 return m_path.count() + 1;
281 }
282 return 0;
283}
284
285Node *CriticalPathItemModel::node( const QModelIndex &index ) const
286{
287 if ( ! index.isValid() ) {
288 return 0;
289 }
290 return m_path.value( index.row() );
291}
292
293void CriticalPathItemModel::slotNodeChanged( Node *node )
294{
295 kDebug(planDbg());
296 if ( node == 0 || node->type() == Node::Type_Project || ! m_path.contains( node ) ) {
297 return;
298 }
299 int row = m_path.indexOf( node );
300 emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount() - 1, node ) );
301}
302
303
304//-----------------------------
305PertResultItemModel::PertResultItemModel( QObject *parent )
306 : ItemModelBase( parent ),
307 m_manager( 0 )
308{
309/* connect( this, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()) );
310 connect( this, SIGNAL(modelReset()), SLOT(slotReset()) );*/
311}
312
313PertResultItemModel::~PertResultItemModel()
314{
315}
316
317void PertResultItemModel::slotAboutToBeReset()
318{
319 kDebug(planDbg());
320 clear();
321}
322
323void PertResultItemModel::slotReset()
324{
325 kDebug(planDbg());
326 refresh();
327}
328
329void PertResultItemModel::slotNodeToBeInserted( Node *, int )
330{
331 //kDebug(planDbg())<<node->name();
332 clear();
333}
334
335void PertResultItemModel::slotNodeInserted( Node * /*node*/ )
336{
337 //kDebug(planDbg())<<node->getParent->name()<<"-->"<<node->name();
338 refresh();
339}
340
341void PertResultItemModel::slotNodeToBeRemoved( Node * /*node*/ )
342{
343 //kDebug(planDbg())<<node->name();
344 clear();
345}
346
347void PertResultItemModel::slotNodeRemoved( Node * /*node*/ )
348{
349 //kDebug(planDbg())<<node->name();
350 refresh();
351}
352
353void PertResultItemModel::setProject( Project *project )
354{
355 clear();
356 if ( m_project ) {
357 disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) );
358 disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) );
359 disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) );
360 disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) );
361
362 disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) );
363 disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) );
364 disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) );
365 }
366 m_project = project;
367 m_nodemodel.setProject( project );
368 if ( project ) {
369 connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) );
370 connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) );
371 connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) );
372 connect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) );
373
374 connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) );
375 connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) );
376 connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) );
377 }
378 refresh();
379}
380
381void PertResultItemModel::setManager( ScheduleManager *sm )
382{
383 m_manager = sm;
384 m_nodemodel.setManager( sm );
385 refresh();
386}
387
388void PertResultItemModel::clear()
389{
390 kDebug(planDbg())<<this;
391 foreach ( NodeList *l, m_top ) {
392 int c = l->count();
393 if ( c > 0 ) {
394 // FIXME: gives error msg:
395 // Can't select indexes from different model or with different parents
396 QModelIndex i = index( l );
397 kDebug(planDbg())<<i<<": "<<c;
398// beginRemoveRows( i, 0, c-1 );
399// endRemoveRows();
400 }
401 }
402 m_critical.clear();
403 m_noncritical.clear();
404 if ( ! m_top.isEmpty() ) {
405 beginRemoveRows( QModelIndex(), 0, m_top.count() - 1 );
406 m_top.clear();
407 m_topNames.clear();
408 endRemoveRows();
409 }
410}
411
412void PertResultItemModel::refresh()
413{
414 clear();
415 if ( m_project == 0 ) {
416 return;
417 }
418 long id = m_manager == 0 ? -1 : m_manager->scheduleId();
419 kDebug(planDbg())<<id;
420 if ( id == -1 ) {
421 return;
422 }
423 m_topNames << i18n( "Project" );
424 m_top << &m_dummyList; // dummy
425 const QList< NodeList > *lst = m_project->criticalPathList( id );
426 if ( lst ) {
427 for ( int i = 0; i < lst->count(); ++i ) {
428 m_topNames << i18n( "Critical Path" );
429 m_top.append( const_cast<NodeList*>( &( lst->at( i ) ) ) );
430 kDebug(planDbg())<<m_topNames.last()<<lst->at( i );
431 }
432 if ( lst->isEmpty() ) kDebug(planDbg())<<"No critical path";
433 }
434 foreach( Node* n, m_project->allNodes() ) {
435 if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) {
436 continue;
437 }
438 Task *t = static_cast<Task*>( n );
439 if ( t->inCriticalPath( id ) ) {
440 continue;
441 } else if ( t->isCritical( id ) ) {
442 m_critical.append( t );
443 } else {
444 m_noncritical.append( t );
445 }
446 }
447 if ( ! m_critical.isEmpty() ) {
448 m_topNames << i18n( "Critical" );
449 m_top.append(&m_critical );
450 }
451 if ( ! m_noncritical.isEmpty() ) {
452 m_topNames << i18n( "Non-critical" );
453 m_top.append(&m_noncritical );
454 }
455 if ( ! m_top.isEmpty() ) {
456 kDebug(planDbg())<<m_top;
457 beginInsertRows( QModelIndex(), 0, m_top.count() -1 );
458 endInsertRows();
459 foreach ( NodeList *l, m_top ) {
460 int c = l->count();
461 if ( c > 0 ) {
462 beginInsertRows( index( l ), 0, c-1 );
463 endInsertRows();
464 }
465 }
466 }
467}
468
469Qt::ItemFlags PertResultItemModel::flags( const QModelIndex &index ) const
470{
471 Qt::ItemFlags flags = QAbstractItemModel::flags( index );
472 flags &= ~( Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
473 return flags;
474}
475
476
477QModelIndex PertResultItemModel::parent( const QModelIndex &index ) const
478{
479 if ( !index.isValid() ) {
480 return QModelIndex();
481 }
482 //kDebug(planDbg())<<index.internalPointer()<<": "<<index.row()<<", "<<index.column();
483 int row = index.internalId();
484 if ( row < 0 ) {
485 return QModelIndex(); // top level has no parent
486 }
487 if ( m_top.value( row ) == 0 ) {
488 return QModelIndex();
489 }
490 return createIndex( row, 0, -1 );
491}
492
493QModelIndex PertResultItemModel::index( int row, int column, const QModelIndex &parent ) const
494{
495 if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) {
496 return QModelIndex();
497 }
498 if ( ! parent.isValid() ) {
499 if ( row == 0 ) {
500 QModelIndex idx = createIndex(row, column, -2 ); // project
501 return idx;
502 }
503 if ( row >= m_top.count() ) {
504 return QModelIndex(); // shouldn't happend
505 }
506 QModelIndex idx = createIndex(row, column, -1 );
507 //kDebug(planDbg())<<parent<<", "<<idx;
508 return idx;
509 }
510 if ( parent.row() == 0 ) {
511 return QModelIndex();
512 }
513 NodeList *l = m_top.value( parent.row() );
514 if ( l == 0 ) {
515 return QModelIndex();
516 }
517 QModelIndex i = createIndex(row, column, parent.row() );
518 return i;
519}
520
521// QModelIndex PertResultItemModel::index( const Node *node ) const
522// {
523// if ( m_project == 0 || node == 0 ) {
524// return QModelIndex();
525// }
526// foreach( NodeList *l, m_top ) {
527// int row = l->indexOf( const_cast<Node*>( node ) );
528// if ( row != -1 ) {
529// return createIndex( row, 0, const_cast<Node*>( node ) );
530// }
531// }
532// return QModelIndex();
533// }
534
535QModelIndex PertResultItemModel::index( const NodeList *lst ) const
536{
537 if ( m_project == 0 || lst == 0 ) {
538 return QModelIndex();
539 }
540 NodeList *l = const_cast<NodeList*>( lst );
541 int row = m_top.indexOf( l );
542 if ( row <= 0 ) {
543 return QModelIndex();
544 }
545 return createIndex( row, 0, -1 );
546}
547
548QVariant PertResultItemModel::name( int row, int role ) const
549{
550
551 switch ( role ) {
552 case Qt::DisplayRole:
553 case Qt::EditRole:
554 case Qt::ToolTipRole:
555 return m_topNames.value( row );
556 case Qt::StatusTipRole:
557 case Qt::WhatsThisRole:
558 return QVariant();
559 }
560 return QVariant();
561}
562
563QVariant PertResultItemModel::name( const Node *node, int role ) const
564{
565 switch ( role ) {
566 case Qt::DisplayRole:
567 case Qt::EditRole:
568 case Qt::ToolTipRole:
569 return node->name();
570 case Qt::StatusTipRole:
571 case Qt::WhatsThisRole:
572 return QVariant();
573 }
574 return QVariant();
575}
576
577QVariant PertResultItemModel::earlyStart( const Task *node, int role ) const
578{
579 switch ( role ) {
580 case Qt::DisplayRole:
581 return node->earlyStart( m_manager->scheduleId() );
582 case Qt::ToolTipRole:
583 return KGlobal::locale()->formatDate( node->earlyStart( m_manager->scheduleId() ).date() );
584 case Qt::EditRole:
585 case Qt::StatusTipRole:
586 case Qt::WhatsThisRole:
587 return QVariant();
588 }
589 return QVariant();
590}
591
592QVariant PertResultItemModel::earlyFinish( const Task *node, int role ) const
593{
594 switch ( role ) {
595 case Qt::DisplayRole:
596 return node->earlyFinish( m_manager->scheduleId() );
597 case Qt::ToolTipRole:
598 return KGlobal::locale()->formatDate( node->earlyFinish( m_manager->scheduleId() ).date() );
599 case Qt::EditRole:
600 case Qt::StatusTipRole:
601 case Qt::WhatsThisRole:
602 return QVariant();
603 }
604 return QVariant();
605}
606
607QVariant PertResultItemModel::lateStart( const Task *node, int role ) const
608{
609 switch ( role ) {
610 case Qt::DisplayRole:
611 return node->lateStart( m_manager->scheduleId() );
612 case Qt::ToolTipRole:
613 return KGlobal::locale()->formatDate( node->lateStart( m_manager->scheduleId() ).date() );
614 case Qt::EditRole:
615 break;
616 case Qt::StatusTipRole:
617 case Qt::WhatsThisRole:
618 return QVariant();
619 }
620 return QVariant();
621}
622
623QVariant PertResultItemModel::lateFinish( const Task *node, int role ) const
624{
625 switch ( role ) {
626 case Qt::DisplayRole:
627 return node->lateFinish( m_manager->scheduleId() );
628 case Qt::ToolTipRole:
629 return KGlobal::locale()->formatDate( node->lateFinish( m_manager->scheduleId() ).date() );
630 case Qt::EditRole:
631 break;
632 case Qt::StatusTipRole:
633 case Qt::WhatsThisRole:
634 return QVariant();
635 }
636 return QVariant();
637}
638
639QVariant PertResultItemModel::positiveFloat( const Task *node, int role ) const
640{
641 switch ( role ) {
642 case Qt::DisplayRole:
643 return node->positiveFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction );
644 case Qt::ToolTipRole:
645 return node->positiveFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime );
646 case Qt::EditRole:
647 case Qt::StatusTipRole:
648 case Qt::WhatsThisRole:
649 return QVariant();
650 }
651 return QVariant();
652}
653
654QVariant PertResultItemModel::freeFloat( const Task *node, int role ) const
655{
656 switch ( role ) {
657 case Qt::DisplayRole:
658 return node->freeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction );
659 case Qt::ToolTipRole:
660 return node->freeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime );
661 case Qt::EditRole:
662 case Qt::StatusTipRole:
663 case Qt::WhatsThisRole:
664 return QVariant();
665 }
666 return QVariant();
667}
668
669QVariant PertResultItemModel::negativeFloat( const Task *node, int role ) const
670{
671 switch ( role ) {
672 case Qt::DisplayRole:
673 return node->negativeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction );
674 case Qt::ToolTipRole:
675 return node->negativeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime );
676 case Qt::EditRole:
677 case Qt::StatusTipRole:
678 case Qt::WhatsThisRole:
679 return QVariant();
680 }
681 return QVariant();
682}
683
684QVariant PertResultItemModel::startFloat( const Task *node, int role ) const
685{
686 switch ( role ) {
687 case Qt::DisplayRole:
688 return node->startFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction );
689 case Qt::ToolTipRole:
690 return node->startFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime );
691 case Qt::EditRole:
692 case Qt::StatusTipRole:
693 case Qt::WhatsThisRole:
694 return QVariant();
695 }
696 return QVariant();
697}
698
699QVariant PertResultItemModel::finishFloat( const Task *node, int role ) const
700{
701 switch ( role ) {
702 case Qt::DisplayRole:
703 return node->finishFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction );
704 case Qt::ToolTipRole:
705 return node->finishFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime );
706 case Qt::EditRole:
707 case Qt::StatusTipRole:
708 case Qt::WhatsThisRole:
709 return QVariant();
710 }
711 return QVariant();
712}
713
714QVariant PertResultItemModel::data( const QModelIndex &index, int role ) const
715{
716 QVariant result;
717 if ( ! index.isValid() ) {
718 return result;
719 }
720 if ( role == Qt::TextAlignmentRole ) {
721 return alignment( index.column() );
722 }
723 Node *n = node( index );
724 if ( n == 0 ) {
725 switch ( index.column() ) {
726 case 0: return name( index.row(), role );
727 default: break;
728 }
729 return QVariant();
730 }
731 if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) {
732 result = m_nodemodel.data( n, index.column(), role );
733 }
734 if ( n->type() == Node::Type_Project ) {
735 //Project *p = static_cast<Project*>( n );
736 switch ( index.column() ) {
737 case NodeModel::NodeName: result = name( NodeModel::NodeName, role ); break;
738 default:
739 //kDebug(planDbg())<<"data: invalid display value column "<<index.column();
740 return QVariant();
741 }
742 }
743 if ( result.isValid() ) {
744 if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) {
745 // HACK to show focus in empty cells
746 result = ' ';
747 }
748 return result;
749 }
750 return QVariant();
751}
752
753QVariant PertResultItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
754{
755 if ( orientation == Qt::Horizontal ) {
756 if ( role == Qt::DisplayRole ) {
757 return m_nodemodel.headerData( section, role );
758 } else if ( role == Qt::TextAlignmentRole ) {
759 return alignment( section );
760 }
761 }
762 if ( role == Qt::ToolTipRole ) {
763 return m_nodemodel.headerData( section, role );
764 } else if ( role == Qt::WhatsThisRole ) {
765 return m_nodemodel.headerData( section, role );
766 }
767 return ItemModelBase::headerData(section, orientation, role);
768}
769
770QVariant PertResultItemModel::alignment( int column ) const
771{
772 return m_nodemodel.headerData( column, Qt::TextAlignmentRole );
773}
774
775QAbstractItemDelegate *PertResultItemModel::createDelegate( int column, QWidget * /*parent*/ ) const
776{
777 switch ( column ) {
778 default: return 0;
779 }
780 return 0;
781}
782
783int PertResultItemModel::columnCount( const QModelIndex & ) const
784{
785 return m_nodemodel.propertyCount();
786}
787
788int PertResultItemModel::rowCount( const QModelIndex &parent ) const
789{
790 if ( ! parent.isValid() ) {
791 //kDebug(planDbg())<<"top="<<m_top.count();
792 return m_top.count();
793 }
794 NodeList *l = list( parent );
795 if ( l ) {
796 //kDebug(planDbg())<<"list "<<parent.row()<<": "<<l->count();
797 return l->count();
798 }
799 //kDebug(planDbg())<<"node "<<parent.row();
800 return 0; // nodes don't have children
801}
802
803Qt::DropActions PertResultItemModel::supportedDropActions() const
804{
805 return (Qt::DropActions)Qt::CopyAction | Qt::MoveAction;
806}
807
808
809QStringList PertResultItemModel::mimeTypes() const
810{
811 return QStringList();
812}
813
814QMimeData *PertResultItemModel::mimeData( const QModelIndexList & ) const
815{
816 QMimeData *m = new QMimeData();
817 return m;
818}
819
820bool PertResultItemModel::dropAllowed( Node *, const QMimeData * )
821{
822 return false;
823}
824
825bool PertResultItemModel::dropMimeData( const QMimeData *, Qt::DropAction , int , int , const QModelIndex & )
826{
827 return false;
828}
829
830NodeList *PertResultItemModel::list( const QModelIndex &index ) const
831{
832 if ( index.isValid() && index.internalId() == -1 ) {
833 //kDebug(planDbg())<<index<<"is list: "<<m_top.value( index.row() );
834 return m_top.value( index.row() );
835 }
836 //kDebug(planDbg())<<index<<"is not list";
837 return 0;
838}
839
840Node *PertResultItemModel::node( const QModelIndex &index ) const
841{
842 if ( ! index.isValid() ) {
843 return 0;
844 }
845 if ( index.internalId() == -2 ) {
846 return m_project;
847 }
848 if ( index.internalId() == 0 ) {
849 return 0;
850 }
851 NodeList *l = m_top.value( index.internalId() );
852 if ( l ) {
853 return l->value( index.row() );
854 }
855 return 0;
856}
857
858void PertResultItemModel::slotNodeChanged( Node *)
859{
860 kDebug(planDbg());
861 refresh();
862/* if ( node == 0 || node->type() == Node::Type_Project ) {
863 return;
864 }
865 int row = node->getParent()->findChildNode( node );
866 emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount() - 1, node ) );*/
867}
868
869
870} // namespace KPlato
871
872#include "kptpertcpmmodel.moc"
873