1 | /* This file is part of the KDE project |
2 | Copyright (C) 2007 - 2009, 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 | #include "kptnodeitemmodel.h" |
21 | |
22 | #include "kptglobal.h" |
23 | #include "kptcommonstrings.h" |
24 | #include "kptcommand.h" |
25 | #include "kptduration.h" |
26 | #include "kptproject.h" |
27 | #include "kptnode.h" |
28 | #include "kpttaskcompletedelegate.h" |
29 | #include "kptxmlloaderobject.h" |
30 | #include "kptdebug.h" |
31 | |
32 | #include "KoStore.h" |
33 | #include <KoIcon.h> |
34 | |
35 | #include <QAbstractItemModel> |
36 | #include <QMimeData> |
37 | #include <QModelIndex> |
38 | #include <QWidget> |
39 | #include <QPair> |
40 | #include <QByteArray> |
41 | |
42 | #include <kaction.h> |
43 | #include <kglobal.h> |
44 | #include <klocale.h> |
45 | #include <ktoggleaction.h> |
46 | #include <kactionmenu.h> |
47 | #include <kstandardaction.h> |
48 | #include <kstandardshortcut.h> |
49 | #include <kaccelgen.h> |
50 | #include <kactioncollection.h> |
51 | #include <krichtextwidget.h> |
52 | #include <kmimetype.h> |
53 | |
54 | #include <kdganttglobal.h> |
55 | #include <math.h> |
56 | |
57 | |
58 | namespace KPlato |
59 | { |
60 | |
61 | |
62 | //-------------------------------------- |
63 | NodeModel::NodeModel() |
64 | : QObject(), |
65 | m_project( 0 ), |
66 | m_manager( 0 ), |
67 | m_now( QDate::currentDate() ), |
68 | m_prec( 1 ) |
69 | { |
70 | } |
71 | |
72 | const QMetaEnum NodeModel::columnMap() const |
73 | { |
74 | return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties" ) ); |
75 | } |
76 | |
77 | void NodeModel::setProject( Project *project ) |
78 | { |
79 | kDebug(planDbg())<<m_project<<"->" <<project; |
80 | m_project = project; |
81 | } |
82 | |
83 | void NodeModel::setManager( ScheduleManager *sm ) |
84 | { |
85 | kDebug(planDbg())<<m_manager<<"->" <<sm; |
86 | m_manager = sm; |
87 | } |
88 | |
89 | QVariant NodeModel::name( const Node *node, int role ) const |
90 | { |
91 | switch ( role ) { |
92 | case Qt::DisplayRole: |
93 | case Qt::EditRole: |
94 | case Qt::ToolTipRole: |
95 | return node->name(); |
96 | case Qt::StatusTipRole: |
97 | case Qt::WhatsThisRole: |
98 | return QVariant(); |
99 | case Qt::DecorationRole: |
100 | if ( node->isBaselined() ) { |
101 | return koIcon("view-time-schedule-baselined" ); |
102 | } |
103 | break; |
104 | case Role::Foreground: { |
105 | if ( ! m_project ) { |
106 | break; |
107 | } |
108 | switch ( node->type() ) { |
109 | case Node::Type_Task: |
110 | return static_cast<const Task*>( node )->completion().isFinished() ? m_project->config().taskFinishedColor() : m_project->config().taskNormalColor(); |
111 | case Node::Type_Milestone: |
112 | return static_cast<const Task*>( node )->completion().isFinished() ? m_project->config().milestoneFinishedColor() : m_project->config().milestoneNormalColor(); |
113 | case Node::Type_Summarytask: |
114 | return m_project->config().summaryTaskLevelColor( node->level() ); |
115 | default: |
116 | break; |
117 | } |
118 | break; |
119 | } |
120 | } |
121 | return QVariant(); |
122 | } |
123 | |
124 | QVariant NodeModel::leader( const Node *node, int role ) const |
125 | { |
126 | switch ( role ) { |
127 | case Qt::DisplayRole: |
128 | case Qt::EditRole: |
129 | case Qt::ToolTipRole: |
130 | return node->leader(); |
131 | case Qt::StatusTipRole: |
132 | case Qt::WhatsThisRole: |
133 | return QVariant(); |
134 | } |
135 | return QVariant(); |
136 | } |
137 | |
138 | QVariant NodeModel::allocation( const Node *node, int role ) const |
139 | { |
140 | if ( node->type() == Node::Type_Task ) { |
141 | switch ( role ) { |
142 | case Qt::DisplayRole: |
143 | case Qt::EditRole: |
144 | return node->requests().requestNameList().join( "," ); |
145 | case Qt::ToolTipRole: { |
146 | QMap<QString, QStringList> lst; |
147 | foreach ( ResourceRequest *rr, node->requests().resourceRequests( false ) ) { |
148 | QStringList sl; |
149 | foreach( Resource *r, rr->requiredResources() ) { |
150 | sl << r->name(); |
151 | } |
152 | lst.insert( rr->resource()->name(), sl ); |
153 | } |
154 | if ( lst.isEmpty() ) { |
155 | return i18nc( "@info:tooltip" , "No resources has been allocated" ); |
156 | } |
157 | QStringList sl; |
158 | for ( QMap<QString, QStringList>::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) { |
159 | if ( it.value().isEmpty() ) { |
160 | sl << it.key(); |
161 | } else { |
162 | sl << i18nc( "@info:tooltip 1=resource name, 2=list of requiered resources" , "%1 (%2)" , it.key(), it.value().join(", " ) ); |
163 | } |
164 | } |
165 | if ( sl.count() == 1 ) { |
166 | return i18nc( "@info:tooltip 1=resource name" , "Allocated resource:<nl/>%1" , sl.first() ); |
167 | } |
168 | return i18nc( "@info:tooltip 1=list of resources" , "Allocated resources:<nl/>%1" , sl.join( "<nl/>" ) ); |
169 | } |
170 | case Qt::StatusTipRole: |
171 | case Qt::WhatsThisRole: |
172 | return QVariant(); |
173 | } |
174 | } |
175 | return QVariant(); |
176 | } |
177 | |
178 | QVariant NodeModel::description( const Node *node, int role ) const |
179 | { |
180 | switch ( role ) { |
181 | case Qt::DisplayRole: { |
182 | KRichTextWidget w( node->description(), 0 ); |
183 | w.switchToPlainText(); |
184 | QString s = w.textOrHtml(); |
185 | int i = s.indexOf( '\n' ); |
186 | s = s.left( i ); |
187 | if ( i > 0 ) { |
188 | s += "..." ; |
189 | } |
190 | return s; |
191 | } |
192 | case Qt::ToolTipRole: { |
193 | KRichTextWidget w( node->description(), 0 ); |
194 | w.switchToPlainText(); |
195 | if ( w.textOrHtml().isEmpty() ) { |
196 | return QVariant(); |
197 | } |
198 | return node->description(); |
199 | } |
200 | case Qt::EditRole: |
201 | return node->description(); |
202 | case Qt::StatusTipRole: |
203 | case Qt::WhatsThisRole: |
204 | return QVariant(); |
205 | } |
206 | return QVariant(); |
207 | } |
208 | |
209 | QVariant NodeModel::type( const Node *node, int role ) const |
210 | { |
211 | //kDebug(planDbg())<<node->name()<<", "<<role; |
212 | switch ( role ) { |
213 | case Qt::DisplayRole: |
214 | case Qt::ToolTipRole: |
215 | return node->typeToString( true ); |
216 | case Qt::EditRole: |
217 | return node->type(); |
218 | case Qt::TextAlignmentRole: |
219 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
220 | case Qt::StatusTipRole: |
221 | case Qt::WhatsThisRole: |
222 | return QVariant(); |
223 | } |
224 | return QVariant(); |
225 | } |
226 | |
227 | QVariant NodeModel::constraint( const Node *node, int role ) const |
228 | { |
229 | if ( node->type() == Node::Type_Project ) { |
230 | switch ( role ) { |
231 | case Qt::DisplayRole: |
232 | return i18n( "Target times" ); |
233 | case Qt::ToolTipRole: |
234 | return i18nc( "@info:tooltip" , "Earliest start and latest finish" ); |
235 | case Role::EnumList: |
236 | case Qt::EditRole: |
237 | case Role::EnumListValue: |
238 | return QVariant(); |
239 | case Qt::TextAlignmentRole: |
240 | return Qt::AlignCenter; |
241 | case Qt::StatusTipRole: |
242 | case Qt::WhatsThisRole: |
243 | return QVariant(); |
244 | } |
245 | } else if ( node->type() != Node::Type_Summarytask ) { |
246 | switch ( role ) { |
247 | case Qt::DisplayRole: |
248 | case Qt::ToolTipRole: |
249 | return node->constraintToString( true ); |
250 | case Role::EnumList: |
251 | return Node::constraintList( true ); |
252 | case Qt::EditRole: |
253 | return node->constraint(); |
254 | case Role::EnumListValue: |
255 | return (int)node->constraint(); |
256 | case Qt::TextAlignmentRole: |
257 | return Qt::AlignCenter; |
258 | case Qt::StatusTipRole: |
259 | case Qt::WhatsThisRole: |
260 | return QVariant(); |
261 | } |
262 | } |
263 | return QVariant(); |
264 | } |
265 | |
266 | QVariant NodeModel::constraintStartTime( const Node *node, int role ) const |
267 | { |
268 | if ( node->type() == Node::Type_Project ) { |
269 | switch ( role ) { |
270 | case Qt::DisplayRole: { |
271 | return KGlobal::locale()->formatDateTime( node->constraintStartTime() ); |
272 | } |
273 | case Qt::ToolTipRole: { |
274 | return KGlobal::locale()->formatDateTime( node->constraintStartTime(), KLocale::LongDate, KLocale::TimeZone ); |
275 | } |
276 | case Qt::EditRole: |
277 | return node->constraintStartTime(); |
278 | case Qt::StatusTipRole: |
279 | case Qt::WhatsThisRole: |
280 | return QVariant(); |
281 | } |
282 | return QVariant(); |
283 | } else if ( node->type() != Node::Type_Summarytask ) { |
284 | switch ( role ) { |
285 | case Qt::DisplayRole: { |
286 | QString s = KGlobal::locale()->formatDateTime( node->constraintStartTime() ); |
287 | switch ( node->constraint() ) { |
288 | case Node::StartNotEarlier: |
289 | case Node::MustStartOn: |
290 | case Node::FixedInterval: |
291 | return s; |
292 | default: |
293 | break; |
294 | } |
295 | return QString( "(%1)" ).arg( s ); |
296 | } |
297 | case Qt::ToolTipRole: { |
298 | int c = node->constraint(); |
299 | if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) { |
300 | return KGlobal::locale()->formatDateTime( node->constraintStartTime(), KLocale::LongDate, KLocale::TimeZone ); |
301 | } |
302 | break; |
303 | } |
304 | case Qt::EditRole: |
305 | return node->constraintStartTime(); |
306 | case Qt::StatusTipRole: |
307 | case Qt::WhatsThisRole: |
308 | return QVariant(); |
309 | } |
310 | } |
311 | return QVariant(); |
312 | } |
313 | |
314 | QVariant NodeModel::constraintEndTime( const Node *node, int role ) const |
315 | { |
316 | if ( node->type() == Node::Type_Project ) { |
317 | switch ( role ) { |
318 | case Qt::DisplayRole: { |
319 | return KGlobal::locale()->formatDateTime( node->constraintEndTime() ); |
320 | } |
321 | case Qt::ToolTipRole: { |
322 | return KGlobal::locale()->formatDateTime( node->constraintEndTime(), KLocale::LongDate, KLocale::TimeZone ); |
323 | } |
324 | case Qt::EditRole: |
325 | return node->constraintEndTime(); |
326 | case Qt::StatusTipRole: |
327 | case Qt::WhatsThisRole: |
328 | return QVariant(); |
329 | } |
330 | return QVariant(); |
331 | } else if ( node->type() != Node::Type_Summarytask ) { |
332 | switch ( role ) { |
333 | case Qt::DisplayRole: { |
334 | QString s = KGlobal::locale()->formatDateTime( node->constraintEndTime() ); |
335 | switch ( node->constraint() ) { |
336 | case Node::FinishNotLater: |
337 | case Node::MustFinishOn: |
338 | case Node::FixedInterval: |
339 | return s; |
340 | default: |
341 | break; |
342 | } |
343 | return QString( "(%1)" ).arg( s ); |
344 | } |
345 | case Qt::ToolTipRole: { |
346 | int c = node->constraint(); |
347 | if ( c == Node::FinishNotLater || c == Node::MustFinishOn || c == Node::FixedInterval ) { |
348 | return KGlobal::locale()->formatDateTime( node->constraintEndTime(), KLocale::LongDate, KLocale::TimeZone ); |
349 | } |
350 | break; |
351 | } |
352 | case Qt::EditRole: |
353 | return node->constraintEndTime(); |
354 | case Qt::StatusTipRole: |
355 | case Qt::WhatsThisRole: |
356 | return QVariant(); |
357 | } |
358 | } |
359 | return QVariant(); |
360 | } |
361 | |
362 | QVariant NodeModel::estimateType( const Node *node, int role ) const |
363 | { |
364 | if ( node->estimate() == 0 ) { |
365 | return QVariant(); |
366 | } |
367 | switch ( role ) { |
368 | case Qt::DisplayRole: |
369 | case Qt::ToolTipRole: |
370 | if ( node->type() == Node::Type_Task ) { |
371 | return node->estimate()->typeToString( true ); |
372 | } |
373 | return QString(); |
374 | case Role::EnumList: |
375 | return Estimate::typeToStringList( true ); |
376 | case Qt::EditRole: |
377 | if ( node->type() == Node::Type_Task ) { |
378 | return node->estimate()->typeToString(); |
379 | } |
380 | return QString(); |
381 | case Role::EnumListValue: |
382 | return (int)node->estimate()->type(); |
383 | case Qt::StatusTipRole: |
384 | case Qt::WhatsThisRole: |
385 | return QVariant(); |
386 | } |
387 | return QVariant(); |
388 | } |
389 | |
390 | QVariant NodeModel::estimateCalendar( const Node *node, int role ) const |
391 | { |
392 | if ( node->estimate() == 0 ) { |
393 | return QVariant(); |
394 | } |
395 | switch ( role ) { |
396 | case Qt::DisplayRole: |
397 | if ( node->type() == Node::Type_Task ) { |
398 | if ( node->estimate()->calendar() ) { |
399 | return node->estimate()->calendar()->name(); |
400 | } |
401 | return i18n( "None" ); |
402 | } |
403 | return QString(); |
404 | case Qt::ToolTipRole: |
405 | if ( node->type() == Node::Type_Task ) { |
406 | if ( node->estimate()->type() == Estimate::Type_Effort ) { |
407 | return i18nc( "@info:tooltip" , "Not applicable, estimate type is Effort" ); |
408 | } |
409 | if ( node->estimate()->calendar() ) { |
410 | return node->estimate()->calendar()->name(); |
411 | } |
412 | return QVariant(); |
413 | } |
414 | return QString(); |
415 | case Role::EnumList: |
416 | { |
417 | QStringList lst; lst << i18n( "None" ); |
418 | const Node *n = const_cast<Node*>( node )->projectNode(); |
419 | if ( n ) { |
420 | lst += static_cast<const Project*>( n )->calendarNames(); |
421 | } |
422 | return lst; |
423 | } |
424 | case Qt::EditRole: |
425 | if ( node->type() == Node::Type_Task ) { |
426 | if ( node->estimate()->calendar() == 0 ) { |
427 | return i18n( "None" ); |
428 | } |
429 | return node->estimate()->calendar()->name(); |
430 | } |
431 | return QString(); |
432 | case Role::EnumListValue: |
433 | { |
434 | if ( node->estimate()->calendar() == 0 ) { |
435 | return 0; |
436 | } |
437 | QStringList lst; |
438 | const Node *n = const_cast<Node*>( node )->projectNode(); |
439 | if ( n ) { |
440 | lst = static_cast<const Project*>( n )->calendarNames(); |
441 | } |
442 | return lst.indexOf( node->estimate()->calendar()->name() ) + 1; |
443 | } |
444 | case Qt::StatusTipRole: |
445 | case Qt::WhatsThisRole: |
446 | return QVariant(); |
447 | } |
448 | return QVariant(); |
449 | } |
450 | |
451 | QVariant NodeModel::estimate( const Node *node, int role ) const |
452 | { |
453 | if ( node->estimate() == 0 ) { |
454 | return QVariant(); |
455 | } |
456 | switch ( role ) { |
457 | case Qt::DisplayRole: |
458 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
459 | Duration::Unit unit = node->estimate()->unit(); |
460 | QString s = KGlobal::locale()->formatNumber( node->estimate()->expectedEstimate(), m_prec ) + Duration::unitToString( unit, true ); |
461 | if ( node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { |
462 | s = '(' + s + ')'; |
463 | } |
464 | return s; |
465 | } |
466 | break; |
467 | case Qt::ToolTipRole: |
468 | if ( node->type() == Node::Type_Task ) { |
469 | Duration::Unit unit = node->estimate()->unit(); |
470 | QString s = KGlobal::locale()->formatNumber( node->estimate()->expectedEstimate(), m_prec ) + Duration::unitToString( unit, true ); |
471 | Estimate::Type t = node->estimate()->type(); |
472 | if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { |
473 | s = i18nc( "@info:tooltip" , "Not applicable, constraint is Fixed Interval" ); |
474 | } else if ( t == Estimate::Type_Effort ) { |
475 | s = i18nc( "@info:tooltip" , "Estimated effort: %1" , s ); |
476 | } else { |
477 | s = i18nc( "@info:tooltip" , "Estimated duration: %1" , s ); |
478 | } |
479 | return s; |
480 | } |
481 | break; |
482 | case Qt::EditRole: |
483 | return node->estimate()->expectedEstimate(); |
484 | case Role::DurationUnit: |
485 | return static_cast<int>( node->estimate()->unit() ); |
486 | case Role::Minimum: |
487 | return m_project->config().minimumDurationUnit(); |
488 | case Role::Maximum: |
489 | return m_project->config().maximumDurationUnit(); |
490 | case Qt::StatusTipRole: |
491 | case Qt::WhatsThisRole: |
492 | return QVariant(); |
493 | } |
494 | return QVariant(); |
495 | } |
496 | |
497 | QVariant NodeModel::optimisticRatio( const Node *node, int role ) const |
498 | { |
499 | if ( node->estimate() == 0 || node->type() == Node::Type_Summarytask || node->type() == Node::Type_Milestone ) { |
500 | return QVariant(); |
501 | } |
502 | switch ( role ) { |
503 | case Qt::DisplayRole: |
504 | if ( node->type() == Node::Type_Task && node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { |
505 | QString s = QString::number( node->estimate()->optimisticRatio() ); |
506 | s = '(' + s + ')'; |
507 | return s; |
508 | } |
509 | if ( node->estimate() ) { |
510 | return node->estimate()->optimisticRatio(); |
511 | } |
512 | break; |
513 | case Qt::EditRole: |
514 | if ( node->estimate() ) { |
515 | return node->estimate()->optimisticRatio(); |
516 | } |
517 | break; |
518 | case Qt::ToolTipRole: |
519 | if ( node->type() == Node::Type_Task ) { |
520 | Duration::Unit unit = node->estimate()->unit(); |
521 | QString s = KGlobal::locale()->formatNumber( node->estimate()->optimisticEstimate(), m_prec ) + Duration::unitToString( unit, true ); |
522 | Estimate::Type t = node->estimate()->type(); |
523 | if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { |
524 | s = i18nc( "@info:tooltip" , "Not applicable, constraint is Fixed Interval" ); |
525 | } else if ( t == Estimate::Type_Effort ) { |
526 | s = i18nc( "@info:tooltip" , "Optimistic effort: %1" , s ); |
527 | } else { |
528 | s = i18nc( "@info:tooltip" , "Optimistic duration: %1" , s ); |
529 | } |
530 | return s; |
531 | } |
532 | break; |
533 | case Role::Minimum: |
534 | return -99; |
535 | case Role::Maximum: |
536 | return 0; |
537 | case Qt::StatusTipRole: |
538 | case Qt::WhatsThisRole: |
539 | return QVariant(); |
540 | } |
541 | return QVariant(); |
542 | } |
543 | |
544 | QVariant NodeModel::pessimisticRatio( const Node *node, int role ) const |
545 | { |
546 | if ( node->estimate() == 0 || node->type() == Node::Type_Summarytask || node->type() == Node::Type_Milestone ) { |
547 | return QVariant(); |
548 | } |
549 | switch ( role ) { |
550 | case Qt::DisplayRole: |
551 | if ( node->type() == Node::Type_Task && node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { |
552 | QString s = QString::number( node->estimate()->pessimisticRatio() ); |
553 | s = '(' + s + ')'; |
554 | return s; |
555 | } |
556 | if ( node->estimate() ) { |
557 | return node->estimate()->pessimisticRatio(); |
558 | } |
559 | break; |
560 | case Qt::EditRole: |
561 | if ( node->estimate() ) { |
562 | return node->estimate()->pessimisticRatio(); |
563 | } |
564 | break; |
565 | case Qt::ToolTipRole: |
566 | if ( node->type() == Node::Type_Task ) { |
567 | Duration::Unit unit = node->estimate()->unit(); |
568 | QString s = KGlobal::locale()->formatNumber( node->estimate()->pessimisticEstimate(), m_prec ) + Duration::unitToString( unit, true ); |
569 | Estimate::Type t = node->estimate()->type(); |
570 | if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { |
571 | s = i18nc( "@info:tooltip" , "Not applicable, constraint is Fixed Interval" ); |
572 | } else if ( t == Estimate::Type_Effort ) { |
573 | s = i18nc( "@info:tooltip" , "Pessimistic effort: %1" , s ); |
574 | } else { |
575 | s = i18nc( "@info:tooltip" , "Pessimistic duration: %1" , s ); |
576 | } |
577 | return s; |
578 | } |
579 | break; |
580 | case Role::Minimum: |
581 | return 0; |
582 | case Role::Maximum: |
583 | return INT_MAX; |
584 | case Qt::StatusTipRole: |
585 | case Qt::WhatsThisRole: |
586 | return QVariant(); |
587 | } |
588 | return QVariant(); |
589 | } |
590 | |
591 | QVariant NodeModel::riskType( const Node *node, int role ) const |
592 | { |
593 | if ( node->estimate() == 0 ) { |
594 | return QVariant(); |
595 | } |
596 | switch ( role ) { |
597 | case Qt::DisplayRole: |
598 | case Qt::ToolTipRole: |
599 | if ( node->type() == Node::Type_Task ) { |
600 | return node->estimate()->risktypeToString( true ); |
601 | } |
602 | return QString(); |
603 | case Role::EnumList: |
604 | return Estimate::risktypeToStringList( true ); |
605 | case Qt::EditRole: |
606 | if ( node->type() == Node::Type_Task ) { |
607 | return node->estimate()->risktypeToString(); |
608 | } |
609 | return QString(); |
610 | case Role::EnumListValue: |
611 | return (int)node->estimate()->risktype(); |
612 | case Qt::StatusTipRole: |
613 | case Qt::WhatsThisRole: |
614 | return QVariant(); |
615 | } |
616 | return QVariant(); |
617 | } |
618 | |
619 | QVariant NodeModel::runningAccount( const Node *node, int role ) const |
620 | { |
621 | switch ( role ) { |
622 | case Qt::DisplayRole: |
623 | if ( node->type() == Node::Type_Task ) { |
624 | Account *a = node->runningAccount(); |
625 | return a == 0 ? i18n( "None" ) : a->name(); |
626 | } |
627 | break; |
628 | case Qt::ToolTipRole: |
629 | if ( node->type() == Node::Type_Task ) { |
630 | Account *a = node->runningAccount(); |
631 | return a ? i18nc( "@info:tooltip" , "Account for resource cost: %1" , a->name() ) |
632 | : i18nc( "@info:tooltip" , "Account for resource cost" ); |
633 | } |
634 | break; |
635 | case Role::EnumListValue: |
636 | case Qt::EditRole: { |
637 | Account *a = node->runningAccount(); |
638 | return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); |
639 | } |
640 | case Role::EnumList: { |
641 | QStringList lst; |
642 | lst << i18n("None" ); |
643 | lst += m_project->accounts().costElements(); |
644 | return lst; |
645 | } |
646 | case Qt::StatusTipRole: |
647 | case Qt::WhatsThisRole: |
648 | return QVariant(); |
649 | } |
650 | return QVariant(); |
651 | } |
652 | |
653 | QVariant NodeModel::startupAccount( const Node *node, int role ) const |
654 | { |
655 | switch ( role ) { |
656 | case Qt::DisplayRole: |
657 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
658 | Account *a = node->startupAccount(); |
659 | //kDebug(planDbg())<<node->name()<<": "<<a; |
660 | return a == 0 ? i18n( "None" ) : a->name(); |
661 | } |
662 | break; |
663 | case Qt::ToolTipRole: |
664 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
665 | Account *a = node->startupAccount(); |
666 | //kDebug(planDbg())<<node->name()<<": "<<a; |
667 | return a ? i18nc( "@info:tooltip" , "Account for task startup cost: %1" , a->name() ) |
668 | : i18nc( "@info:tooltip" , "Account for task startup cost" ); |
669 | } |
670 | break; |
671 | case Role::EnumListValue: |
672 | case Qt::EditRole: { |
673 | Account *a = node->startupAccount(); |
674 | return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); |
675 | } |
676 | case Role::EnumList: { |
677 | QStringList lst; |
678 | lst << i18n("None" ); |
679 | lst += m_project->accounts().costElements(); |
680 | return lst; |
681 | } |
682 | case Qt::StatusTipRole: |
683 | case Qt::WhatsThisRole: |
684 | return QVariant(); |
685 | } |
686 | return QVariant(); |
687 | } |
688 | |
689 | QVariant NodeModel::startupCost( const Node *node, int role ) const |
690 | { |
691 | switch ( role ) { |
692 | case Qt::DisplayRole: |
693 | case Qt::ToolTipRole: |
694 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
695 | return m_project->locale()->formatMoney( node->startupCost() ); |
696 | } |
697 | break; |
698 | case Qt::EditRole: |
699 | return node->startupCost(); |
700 | case Qt::StatusTipRole: |
701 | case Qt::WhatsThisRole: |
702 | return QVariant(); |
703 | } |
704 | return QVariant(); |
705 | } |
706 | |
707 | QVariant NodeModel::shutdownAccount( const Node *node, int role ) const |
708 | { |
709 | switch ( role ) { |
710 | case Qt::DisplayRole: |
711 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
712 | Account *a = node->shutdownAccount(); |
713 | return a == 0 ? i18n( "None" ) : a->name(); |
714 | } |
715 | break; |
716 | case Qt::ToolTipRole: |
717 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
718 | Account *a = node->shutdownAccount(); |
719 | return a ? i18nc( "@info:tooltip" , "Account for task shutdown cost: %1" , a->name() ) |
720 | : i18nc( "@info:tooltip" , "Account for task shutdown cost" ); |
721 | } |
722 | break; |
723 | case Role::EnumListValue: |
724 | case Qt::EditRole: { |
725 | Account *a = node->shutdownAccount(); |
726 | return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); |
727 | } |
728 | case Role::EnumList: { |
729 | QStringList lst; |
730 | lst << i18n("None" ); |
731 | lst += m_project->accounts().costElements(); |
732 | return lst; |
733 | } |
734 | case Qt::StatusTipRole: |
735 | case Qt::WhatsThisRole: |
736 | return QVariant(); |
737 | } |
738 | return QVariant(); |
739 | } |
740 | |
741 | QVariant NodeModel::shutdownCost( const Node *node, int role ) const |
742 | { |
743 | switch ( role ) { |
744 | case Qt::DisplayRole: |
745 | case Qt::ToolTipRole: |
746 | if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { |
747 | return m_project->locale()->formatMoney( node->shutdownCost() ); |
748 | } |
749 | break; |
750 | case Qt::EditRole: |
751 | return node->shutdownCost(); |
752 | case Qt::StatusTipRole: |
753 | case Qt::WhatsThisRole: |
754 | return QVariant(); |
755 | } |
756 | return QVariant(); |
757 | } |
758 | |
759 | QVariant NodeModel::startTime( const Node *node, int role ) const |
760 | { |
761 | switch ( role ) { |
762 | case Qt::DisplayRole: |
763 | return KGlobal::locale()->formatDateTime( node->startTime( id() ) ); |
764 | case Qt::ToolTipRole: |
765 | //kDebug(planDbg())<<node->name()<<", "<<role; |
766 | return i18nc( "@info:tooltip" , "Scheduled start: %1" , KGlobal::locale()->formatDateTime( node->startTime( id() ), KLocale::LongDate, KLocale::TimeZone ) ); |
767 | case Qt::EditRole: |
768 | return node->startTime( id() ); |
769 | case Qt::StatusTipRole: |
770 | case Qt::WhatsThisRole: |
771 | return QVariant(); |
772 | } |
773 | return QVariant(); |
774 | } |
775 | |
776 | QVariant NodeModel::endTime( const Node *node, int role ) const |
777 | { |
778 | switch ( role ) { |
779 | case Qt::DisplayRole: |
780 | return KGlobal::locale()->formatDateTime( node->endTime( id() ) ); |
781 | case Qt::ToolTipRole: |
782 | //kDebug(planDbg())<<node->name()<<", "<<role; |
783 | return i18nc( "@info:tooltip" , "Scheduled finish: %1" , KGlobal::locale()->formatDateTime( node->endTime( id() ), KLocale::LongDate, KLocale::TimeZone ) ); |
784 | case Qt::EditRole: |
785 | return node->endTime( id() ); |
786 | case Qt::StatusTipRole: |
787 | case Qt::WhatsThisRole: |
788 | return QVariant(); |
789 | } |
790 | return QVariant(); |
791 | } |
792 | |
793 | QVariant NodeModel::duration( const Node *node, int role ) const |
794 | { |
795 | switch ( role ) { |
796 | case Qt::DisplayRole: |
797 | if ( node->type() == Node::Type_Task ) { |
798 | Duration::Unit unit = node->estimate()->unit(); |
799 | double v = node->duration( id() ).toDouble( unit ); |
800 | return QVariant(KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true )); |
801 | } else if ( node->type() == Node::Type_Project ) { |
802 | Duration::Unit unit = Duration::Unit_d; |
803 | double v = node->duration( id() ).toDouble( unit ); |
804 | return QVariant(KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true )); |
805 | } |
806 | break; |
807 | case Qt::ToolTipRole: |
808 | if ( node->type() == Node::Type_Task ) { |
809 | Duration::Unit unit = node->estimate()->unit(); |
810 | double v = node->duration( id() ).toDouble( unit ); |
811 | return i18nc( "@info:tooltip" , "Scheduled duration: %1" , KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true ) ); |
812 | } else if ( node->type() == Node::Type_Project ) { |
813 | Duration::Unit unit = Duration::Unit_d; |
814 | double v = node->duration( id() ).toDouble( unit ); |
815 | return i18nc( "@info:tooltip" , "Scheduled duration: %1" , KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true ) ); |
816 | } |
817 | break; |
818 | case Qt::EditRole: { |
819 | return node->duration( id() ).toDouble( Duration::Unit_h ); |
820 | } |
821 | case Qt::StatusTipRole: |
822 | case Qt::WhatsThisRole: |
823 | return QVariant(); |
824 | } |
825 | return QVariant(); |
826 | } |
827 | |
828 | QVariant NodeModel::varianceDuration( const Node *node, int role ) const |
829 | { |
830 | switch ( role ) { |
831 | case Qt::DisplayRole: |
832 | if ( node->type() == Node::Type_Task ) { |
833 | Duration::Unit unit = node->estimate()->unit(); |
834 | double v = node->variance( id(), unit ); |
835 | return KGlobal::locale()->formatNumber( v ); |
836 | } |
837 | break; |
838 | case Qt::EditRole: |
839 | if ( node->type() == Node::Type_Task ) { |
840 | Duration::Unit unit = node->estimate()->unit(); |
841 | return node->variance( id(), unit ); |
842 | } |
843 | return 0.0; |
844 | case Qt::ToolTipRole: |
845 | if ( node->type() == Node::Type_Task ) { |
846 | Duration::Unit unit = node->estimate()->unit(); |
847 | double v = node->variance( id(), unit ); |
848 | return i18nc( "@info:tooltip" , "PERT duration variance: %1" , KGlobal::locale()->formatNumber( v ) ); |
849 | } |
850 | break; |
851 | case Qt::StatusTipRole: |
852 | case Qt::WhatsThisRole: |
853 | return QVariant(); |
854 | } |
855 | return QVariant(); |
856 | } |
857 | |
858 | QVariant NodeModel::varianceEstimate( const Estimate *est, int role ) const |
859 | { |
860 | switch ( role ) { |
861 | case Qt::DisplayRole: { |
862 | if ( est == 0 ) { |
863 | return QVariant(); |
864 | } |
865 | Duration::Unit unit = est->unit(); |
866 | double v = est->variance( unit ); |
867 | //kDebug(planDbg())<<node->name()<<": "<<v<<" "<<unit<<" : "<<scales; |
868 | return KGlobal::locale()->formatNumber( v ); |
869 | } |
870 | case Qt::EditRole: { |
871 | if ( est == 0 ) { |
872 | return 0.0; |
873 | } |
874 | return est->variance( est->unit() ); |
875 | } |
876 | case Qt::ToolTipRole: { |
877 | if ( est == 0 ) { |
878 | return QVariant(); |
879 | } |
880 | Duration::Unit unit = est->unit(); |
881 | double v = est->variance( unit ); |
882 | return i18nc( "@info:tooltip" , "PERT estimate variance: %1" , KGlobal::locale()->formatNumber( v ) + Duration::unitToString( unit, true ) ); |
883 | } |
884 | case Qt::StatusTipRole: |
885 | case Qt::WhatsThisRole: |
886 | return QVariant(); |
887 | } |
888 | return QVariant(); |
889 | } |
890 | |
891 | QVariant NodeModel::optimisticDuration( const Node *node, int role ) const |
892 | { |
893 | switch ( role ) { |
894 | case Qt::DisplayRole: { |
895 | if ( node->type() != Node::Type_Task ) { |
896 | return QVariant(); |
897 | } |
898 | Duration d = node->duration( id() ); |
899 | d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; |
900 | Duration::Unit unit = node->estimate()->unit(); |
901 | double v = d.toDouble( unit ); |
902 | //kDebug(planDbg())<<node->name()<<": "<<v<<" "<<unit<<" : "<<scales; |
903 | return QVariant(KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true )); |
904 | break; |
905 | } |
906 | case Qt::EditRole: { |
907 | if ( node->type() != Node::Type_Task ) { |
908 | return 0.0; |
909 | } |
910 | Duration d = node->duration( id() ); |
911 | d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; |
912 | Duration::Unit unit = node->estimate()->unit(); |
913 | return d.toDouble( unit ); |
914 | } |
915 | case Qt::ToolTipRole: { |
916 | if ( node->type() != Node::Type_Task ) { |
917 | return QVariant(); |
918 | } |
919 | Duration d = node->duration( id() ); |
920 | d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; |
921 | Duration::Unit unit = node->estimate()->unit(); |
922 | double v = d.toDouble( unit ); |
923 | //kDebug(planDbg())<<node->name()<<": "<<v<<" "<<unit<<" : "<<scales; |
924 | return i18nc( "@info:tooltip" , "PERT optimistic duration: %1" , KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true ) ); |
925 | break; |
926 | } |
927 | case Qt::StatusTipRole: |
928 | case Qt::WhatsThisRole: |
929 | return QVariant(); |
930 | } |
931 | return QVariant(); |
932 | } |
933 | |
934 | QVariant NodeModel::optimisticEstimate( const Estimate *est, int role ) const |
935 | { |
936 | switch ( role ) { |
937 | case Qt::DisplayRole: { |
938 | if ( est == 0 ) { |
939 | return QVariant(); |
940 | } |
941 | Duration::Unit unit = est->unit(); |
942 | return QVariant(KGlobal::locale()->formatNumber( est->optimisticEstimate(), m_prec ) + Duration::unitToString( unit, true )); |
943 | break; |
944 | } |
945 | case Qt::EditRole: { |
946 | if ( est == 0 ) { |
947 | return 0.0; |
948 | } |
949 | return est->optimisticEstimate(); |
950 | } |
951 | case Qt::ToolTipRole: { |
952 | if ( est == 0 ) { |
953 | return QVariant(); |
954 | } |
955 | Duration::Unit unit = est->unit(); |
956 | return i18nc( "@info:tooltip" , "Optimistic estimate: %1" , KGlobal::locale()->formatNumber( est->optimisticEstimate(), m_prec ) + Duration::unitToString( unit, true ) ); |
957 | break; |
958 | } |
959 | case Qt::StatusTipRole: |
960 | case Qt::WhatsThisRole: |
961 | return QVariant(); |
962 | } |
963 | return QVariant(); |
964 | } |
965 | |
966 | QVariant NodeModel::pertExpected( const Estimate *est, int role ) const |
967 | { |
968 | switch ( role ) { |
969 | case Qt::DisplayRole: { |
970 | if ( est == 0 ) { |
971 | return QVariant(); |
972 | } |
973 | Duration::Unit unit = est->unit(); |
974 | double v = Estimate::scale( est->pertExpected(), unit, est->scales() ); |
975 | return QVariant(KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true )); |
976 | } |
977 | case Qt::EditRole: { |
978 | if ( est == 0 ) { |
979 | return 0.0; |
980 | } |
981 | return Estimate::scale( est->pertExpected(), est->unit(), est->scales() ); |
982 | } |
983 | case Qt::ToolTipRole: { |
984 | if ( est == 0 ) { |
985 | return QVariant(); |
986 | } |
987 | Duration::Unit unit = est->unit(); |
988 | double v = Estimate::scale( est->pertExpected(), unit, est->scales() ); |
989 | return i18nc( "@info:tooltip" , "PERT expected estimate: %1" , KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true ) ); |
990 | } |
991 | case Qt::StatusTipRole: |
992 | case Qt::WhatsThisRole: |
993 | return QVariant(); |
994 | } |
995 | return QVariant(); |
996 | } |
997 | |
998 | QVariant NodeModel::pessimisticDuration( const Node *node, int role ) const |
999 | { |
1000 | switch ( role ) { |
1001 | case Qt::DisplayRole: { |
1002 | if ( node->type() != Node::Type_Task ) { |
1003 | return QVariant(); |
1004 | } |
1005 | Duration d = node->duration( id() ); |
1006 | d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; |
1007 | Duration::Unit unit = node->estimate()->unit(); |
1008 | double v = d.toDouble( unit ); |
1009 | //kDebug(planDbg())<<node->name()<<": "<<v<<" "<<unit<<" : "<<scales; |
1010 | return QVariant(KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true )); |
1011 | break; |
1012 | } |
1013 | case Qt::EditRole: { |
1014 | if ( node->type() != Node::Type_Task ) { |
1015 | return 0.0; |
1016 | } |
1017 | Duration d = node->duration( id() ); |
1018 | d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; |
1019 | return d.toDouble( node->estimate()->unit() ); |
1020 | } |
1021 | case Qt::ToolTipRole: { |
1022 | if ( node->type() != Node::Type_Task ) { |
1023 | return QVariant(); |
1024 | } |
1025 | Duration d = node->duration( id() ); |
1026 | d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; |
1027 | Duration::Unit unit = node->estimate()->unit(); |
1028 | double v = d.toDouble( unit ); |
1029 | //kDebug(planDbg())<<node->name()<<": "<<v<<" "<<unit<<" : "<<scales; |
1030 | return i18nc( "@info:tooltip" , "PERT pessimistic duration: %1" , KGlobal::locale()->formatNumber( v, m_prec ) + Duration::unitToString( unit, true ) ); |
1031 | break; |
1032 | } |
1033 | case Qt::StatusTipRole: |
1034 | case Qt::WhatsThisRole: |
1035 | return QVariant(); |
1036 | } |
1037 | return QVariant(); |
1038 | } |
1039 | |
1040 | QVariant NodeModel::pessimisticEstimate( const Estimate *est, int role ) const |
1041 | { |
1042 | switch ( role ) { |
1043 | case Qt::DisplayRole: { |
1044 | if ( est == 0 ) { |
1045 | return QVariant(); |
1046 | } |
1047 | Duration::Unit unit = est->unit(); |
1048 | return QVariant(KGlobal::locale()->formatNumber( est->pessimisticEstimate(), m_prec ) + Duration::unitToString( unit, true )); |
1049 | break; |
1050 | } |
1051 | case Qt::EditRole: { |
1052 | if ( est == 0 ) { |
1053 | return 0.0; |
1054 | } |
1055 | return est->pessimisticEstimate(); |
1056 | } |
1057 | case Qt::ToolTipRole: { |
1058 | if ( est == 0 ) { |
1059 | return QVariant(); |
1060 | } |
1061 | Duration::Unit unit = est->unit(); |
1062 | return i18nc( "@info:tooltip" , "Pessimistic estimate: %1" , KGlobal::locale()->formatNumber( est->pessimisticEstimate(), m_prec ) + Duration::unitToString( unit, true ) ); |
1063 | break; |
1064 | } |
1065 | case Qt::StatusTipRole: |
1066 | case Qt::WhatsThisRole: |
1067 | return QVariant(); |
1068 | } |
1069 | return QVariant(); |
1070 | } |
1071 | |
1072 | QVariant NodeModel::earlyStart( const Node *node, int role ) const |
1073 | { |
1074 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1075 | return QVariant(); |
1076 | } |
1077 | const Task *t = static_cast<const Task*>( node ); |
1078 | switch ( role ) { |
1079 | case Qt::DisplayRole: |
1080 | return KGlobal::locale()->formatDateTime( t->earlyStart( id() ) ); |
1081 | case Qt::ToolTipRole: |
1082 | return KGlobal::locale()->formatDate( t->earlyStart( id() ).date() ); |
1083 | case Qt::EditRole: |
1084 | return t->earlyStart( id() ); |
1085 | case Qt::StatusTipRole: |
1086 | case Qt::WhatsThisRole: |
1087 | return QVariant(); |
1088 | } |
1089 | return QVariant(); |
1090 | } |
1091 | |
1092 | QVariant NodeModel::earlyFinish( const Node *node, int role ) const |
1093 | { |
1094 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1095 | return QVariant(); |
1096 | } |
1097 | const Task *t = static_cast<const Task*>( node ); |
1098 | switch ( role ) { |
1099 | case Qt::DisplayRole: |
1100 | return KGlobal::locale()->formatDateTime( t->earlyFinish( id() ) ); |
1101 | case Qt::ToolTipRole: |
1102 | return KGlobal::locale()->formatDate( t->earlyFinish( id() ).date() ); |
1103 | case Qt::EditRole: |
1104 | return t->earlyFinish( id() ); |
1105 | case Qt::StatusTipRole: |
1106 | case Qt::WhatsThisRole: |
1107 | return QVariant(); |
1108 | } |
1109 | return QVariant(); |
1110 | } |
1111 | |
1112 | QVariant NodeModel::lateStart( const Node *node, int role ) const |
1113 | { |
1114 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1115 | return QVariant(); |
1116 | } |
1117 | const Task *t = static_cast<const Task*>( node ); |
1118 | switch ( role ) { |
1119 | case Qt::DisplayRole: |
1120 | return KGlobal::locale()->formatDateTime( t->lateStart( id() ) ); |
1121 | case Qt::ToolTipRole: |
1122 | return KGlobal::locale()->formatDate( t->lateStart( id() ).date() ); |
1123 | case Qt::EditRole: |
1124 | return t->lateStart( id() ); |
1125 | case Qt::StatusTipRole: |
1126 | case Qt::WhatsThisRole: |
1127 | return QVariant(); |
1128 | } |
1129 | return QVariant(); |
1130 | } |
1131 | |
1132 | QVariant NodeModel::lateFinish( const Node *node, int role ) const |
1133 | { |
1134 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1135 | return QVariant(); |
1136 | } |
1137 | const Task *t = static_cast<const Task*>( node ); |
1138 | switch ( role ) { |
1139 | case Qt::DisplayRole: |
1140 | return KGlobal::locale()->formatDateTime( t->lateFinish( id() ) ); |
1141 | case Qt::ToolTipRole: |
1142 | return KGlobal::locale()->formatDate( t->lateFinish( id() ).date() ); |
1143 | case Qt::EditRole: |
1144 | return t->lateFinish( id() ); |
1145 | case Qt::StatusTipRole: |
1146 | case Qt::WhatsThisRole: |
1147 | return QVariant(); |
1148 | } |
1149 | return QVariant(); |
1150 | } |
1151 | |
1152 | QVariant NodeModel::positiveFloat( const Node *node, int role ) const |
1153 | { |
1154 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1155 | return QVariant(); |
1156 | } |
1157 | const Task *t = static_cast<const Task*>( node ); |
1158 | switch ( role ) { |
1159 | case Qt::DisplayRole: |
1160 | return t->positiveFloat( id() ).toString( Duration::Format_i18nHourFraction ); |
1161 | case Qt::ToolTipRole: |
1162 | return t->positiveFloat( id() ).toString( Duration::Format_i18nDayTime ); |
1163 | case Qt::EditRole: |
1164 | return t->positiveFloat( id() ).toDouble( Duration::Unit_h ); |
1165 | case Qt::StatusTipRole: |
1166 | case Qt::WhatsThisRole: |
1167 | return QVariant(); |
1168 | } |
1169 | return QVariant(); |
1170 | } |
1171 | |
1172 | QVariant NodeModel::freeFloat( const Node *node, int role ) const |
1173 | { |
1174 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1175 | return QVariant(); |
1176 | } |
1177 | const Task *t = static_cast<const Task*>( node ); |
1178 | switch ( role ) { |
1179 | case Qt::DisplayRole: |
1180 | return t->freeFloat( id() ).toString( Duration::Format_i18nHourFraction ); |
1181 | case Qt::ToolTipRole: |
1182 | return t->freeFloat( id() ).toString( Duration::Format_i18nDayTime ); |
1183 | case Qt::EditRole: |
1184 | return t->freeFloat( id() ).toDouble( Duration::Unit_h ); |
1185 | case Qt::StatusTipRole: |
1186 | case Qt::WhatsThisRole: |
1187 | return QVariant(); |
1188 | } |
1189 | return QVariant(); |
1190 | } |
1191 | |
1192 | QVariant NodeModel::negativeFloat( const Node *node, int role ) const |
1193 | { |
1194 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1195 | return QVariant(); |
1196 | } |
1197 | const Task *t = static_cast<const Task*>( node ); |
1198 | switch ( role ) { |
1199 | case Qt::DisplayRole: |
1200 | return t->negativeFloat( id() ).toString( Duration::Format_i18nHourFraction ); |
1201 | case Qt::ToolTipRole: |
1202 | return t->negativeFloat( id() ).toString( Duration::Format_i18nDayTime ); |
1203 | case Qt::EditRole: |
1204 | return t->negativeFloat( id() ).toDouble( Duration::Unit_h ); |
1205 | case Qt::StatusTipRole: |
1206 | case Qt::WhatsThisRole: |
1207 | return QVariant(); |
1208 | } |
1209 | return QVariant(); |
1210 | } |
1211 | |
1212 | QVariant NodeModel::startFloat( const Node *node, int role ) const |
1213 | { |
1214 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1215 | return QVariant(); |
1216 | } |
1217 | const Task *t = static_cast<const Task*>( node ); |
1218 | switch ( role ) { |
1219 | case Qt::DisplayRole: |
1220 | return t->startFloat( id() ).toString( Duration::Format_i18nHourFraction ); |
1221 | case Qt::ToolTipRole: |
1222 | return t->startFloat( id() ).toString( Duration::Format_i18nDayTime ); |
1223 | case Qt::EditRole: |
1224 | return t->startFloat( id() ).toDouble( Duration::Unit_h ); |
1225 | case Qt::StatusTipRole: |
1226 | case Qt::WhatsThisRole: |
1227 | return QVariant(); |
1228 | } |
1229 | return QVariant(); |
1230 | } |
1231 | |
1232 | QVariant NodeModel::finishFloat( const Node *node, int role ) const |
1233 | { |
1234 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1235 | return QVariant(); |
1236 | } |
1237 | const Task *t = static_cast<const Task*>( node ); |
1238 | switch ( role ) { |
1239 | case Qt::DisplayRole: |
1240 | return t->finishFloat( id() ).toString( Duration::Format_i18nHourFraction ); |
1241 | case Qt::ToolTipRole: |
1242 | return t->finishFloat( id() ).toString( Duration::Format_i18nDayTime ); |
1243 | case Qt::EditRole: |
1244 | t->finishFloat( id() ).toDouble( Duration::Unit_h ); |
1245 | case Qt::StatusTipRole: |
1246 | case Qt::WhatsThisRole: |
1247 | return QVariant(); |
1248 | } |
1249 | return QVariant(); |
1250 | } |
1251 | |
1252 | QVariant NodeModel::assignedResources( const Node *node, int role ) const |
1253 | { |
1254 | if ( node->type() != Node::Type_Task ) { |
1255 | return QVariant(); |
1256 | } |
1257 | switch ( role ) { |
1258 | case Qt::DisplayRole: |
1259 | case Qt::EditRole: |
1260 | return node->assignedNameList( id() ).join("," ); |
1261 | case Qt::ToolTipRole: { |
1262 | QStringList lst = node->assignedNameList( id() ); |
1263 | if ( ! lst.isEmpty() ) { |
1264 | return i18nc( "@info:tooltip 1=list of resources" , "Assigned resources:<nl/>%1" , node->assignedNameList( id() ).join("<nl/>" ) ); |
1265 | } |
1266 | break; |
1267 | } |
1268 | case Qt::StatusTipRole: |
1269 | case Qt::WhatsThisRole: |
1270 | return QVariant(); |
1271 | } |
1272 | return QVariant(); |
1273 | } |
1274 | |
1275 | |
1276 | QVariant NodeModel::completed( const Node *node, int role ) const |
1277 | { |
1278 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1279 | return QVariant(); |
1280 | } |
1281 | const Task *t = static_cast<const Task*>( node ); |
1282 | switch ( role ) { |
1283 | case Qt::DisplayRole: |
1284 | return t->completion().percentFinished(); |
1285 | case Qt::EditRole: |
1286 | return t->completion().percentFinished(); |
1287 | case Qt::ToolTipRole: |
1288 | return i18nc( "@info:tooltip" , "Task is %1% completed" , t->completion().percentFinished() ); |
1289 | case Qt::StatusTipRole: |
1290 | case Qt::WhatsThisRole: |
1291 | return QVariant(); |
1292 | } |
1293 | return QVariant(); |
1294 | } |
1295 | |
1296 | QVariant NodeModel::status( const Node *node, int role ) const |
1297 | { |
1298 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1299 | return QVariant(); |
1300 | } |
1301 | const Task *t = static_cast<const Task*>( node ); |
1302 | switch ( role ) { |
1303 | case Qt::DisplayRole: { |
1304 | int st = t->state( id() ); |
1305 | if ( st & Node::State_NotScheduled ) { |
1306 | return SchedulingState::notScheduled(); |
1307 | } |
1308 | if ( st & Node::State_Finished ) { |
1309 | if ( st & Node::State_FinishedLate ) { |
1310 | return i18n( "Finished late" ); |
1311 | } |
1312 | if ( st & Node::State_FinishedEarly ) { |
1313 | return i18n( "Finished early" ); |
1314 | } |
1315 | return i18n( "Finished" ); |
1316 | } |
1317 | if ( st & Node::State_Running ) { |
1318 | if ( st & Node::State_Late ) { |
1319 | return i18n( "Running late" ); |
1320 | } |
1321 | return i18n( "Running" ); |
1322 | } |
1323 | if ( st & Node::State_Started ) { |
1324 | if ( st & Node::State_StartedLate ) { |
1325 | return i18n( "Started late" ); |
1326 | } |
1327 | if ( st & Node::State_StartedEarly ) { |
1328 | return i18n( "Started early" ); |
1329 | } |
1330 | if ( st & Node::State_Late ) { |
1331 | return i18n( "Running late" ); |
1332 | } |
1333 | return i18n( "Started" ); |
1334 | } |
1335 | if ( st & Node::State_ReadyToStart ) { |
1336 | if ( st & Node::State_Late ) { |
1337 | return i18n( "Not started" ); |
1338 | } |
1339 | return i18n( "Can start" ); |
1340 | } |
1341 | if ( st & Node::State_NotReadyToStart ) { |
1342 | if ( st & Node::State_Late ) { |
1343 | return i18n( "Delayed" ); |
1344 | } |
1345 | return i18n( "Cannot start" ); |
1346 | } |
1347 | return i18n( "Not started" ); |
1348 | break; |
1349 | } |
1350 | case Qt::ToolTipRole: { |
1351 | int st = t->state( id() ); |
1352 | if ( st & Node::State_NotScheduled ) { |
1353 | return SchedulingState::notScheduled(); |
1354 | } |
1355 | if ( st & Node::State_Finished ) { |
1356 | if ( st & Node::State_FinishedLate ) { |
1357 | Duration d = t->completion().finishTime() - t->endTime( id() ); |
1358 | return i18nc( "@info:tooltip" , "Finished %1 late" , d.toString( Duration::Format_i18nDay ) ); |
1359 | } |
1360 | if ( st & Node::State_FinishedEarly ) { |
1361 | Duration d = t->endTime( id() ) - t->completion().finishTime(); |
1362 | return i18nc( "@info:tooltip" , "Finished %1 early" , d.toString( Duration::Format_i18nDay ) ); |
1363 | } |
1364 | return i18nc( "@info:tooltip" , "Finished" ); |
1365 | } |
1366 | if ( st & Node::State_Started ) { |
1367 | if ( st & Node::State_StartedLate ) { |
1368 | Duration d = t->completion().startTime() - t->startTime( id() ); |
1369 | return i18nc( "@info:tooltip" , "Started %1 late" , d.toString( Duration::Format_i18nDay ) ); |
1370 | } |
1371 | if ( st & Node::State_StartedEarly ) { |
1372 | Duration d = t->startTime( id() ) - t->completion().startTime(); |
1373 | return i18nc( "@info:tooltip" , "Started %1 early" , d.toString( Duration::Format_i18nDay ) ); |
1374 | } |
1375 | return i18nc( "@info:tooltip" , "Started" ); |
1376 | } |
1377 | if ( st & Node::State_Running ) { |
1378 | return i18nc( "@info:tooltip" , "Running" ); |
1379 | } |
1380 | if ( st & Node::State_ReadyToStart ) { |
1381 | return i18nc( "@info:tooltip" , "Can start" ); |
1382 | } |
1383 | if ( st & Node::State_NotReadyToStart ) { |
1384 | QStringList names; |
1385 | // TODO: proxy relations |
1386 | foreach ( Relation *r, node->dependParentNodes() ) { |
1387 | switch ( r->type() ) { |
1388 | case Relation::FinishFinish: |
1389 | case Relation::FinishStart: |
1390 | if ( ! static_cast<Task*>( r->parent() )->completion().isFinished() ) { |
1391 | if ( ! names.contains( r->parent()->name() ) ) { |
1392 | names << r->parent()->name(); |
1393 | } |
1394 | } |
1395 | break; |
1396 | case Relation::StartStart: |
1397 | if ( ! static_cast<Task*>( r->parent() )->completion().isStarted() ) { |
1398 | if ( ! names.contains( r->parent()->name() ) ) { |
1399 | names << r->parent()->name(); |
1400 | } |
1401 | } |
1402 | break; |
1403 | } |
1404 | } |
1405 | return names.isEmpty() |
1406 | ? i18nc( "@info:tooltip" , "Cannot start" ) |
1407 | : i18nc( "@info:tooltip 1=list of task names" , "Cannot start, waiting for:<nl/>%1" , names.join( "<nl/>" ) ); |
1408 | } |
1409 | return i18nc( "@info:tooltip" , "Not started" ); |
1410 | break; |
1411 | } |
1412 | case Qt::EditRole: |
1413 | return t->state( id() ); |
1414 | case Qt::StatusTipRole: |
1415 | case Qt::WhatsThisRole: |
1416 | return QVariant(); |
1417 | } |
1418 | return QVariant(); |
1419 | } |
1420 | |
1421 | QVariant NodeModel::startedTime( const Node *node, int role ) const |
1422 | { |
1423 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1424 | return QVariant(); |
1425 | } |
1426 | const Task *t = static_cast<const Task*>( node ); |
1427 | switch ( role ) { |
1428 | case Qt::DisplayRole: |
1429 | if ( t->completion().isStarted() ) { |
1430 | return KGlobal::locale()->formatDateTime( t->completion().startTime() ); |
1431 | } |
1432 | break; |
1433 | case Qt::ToolTipRole: |
1434 | if ( t->completion().isStarted() ) { |
1435 | return i18nc( "@info:tooltip" , "Actual start: %1" , KGlobal::locale()->formatDate( t->completion().startTime().date(), KLocale::LongDate ) ); |
1436 | } |
1437 | break; |
1438 | case Qt::EditRole: |
1439 | if ( t->completion().isStarted() ) { |
1440 | return t->completion().startTime(); |
1441 | } |
1442 | return QDateTime::currentDateTime(); |
1443 | case Qt::StatusTipRole: |
1444 | case Qt::WhatsThisRole: |
1445 | return QVariant(); |
1446 | } |
1447 | return QVariant(); |
1448 | } |
1449 | |
1450 | QVariant NodeModel::isStarted( const Node *node, int role ) const |
1451 | { |
1452 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1453 | return QVariant(); |
1454 | } |
1455 | const Task *t = static_cast<const Task*>( node ); |
1456 | switch ( role ) { |
1457 | case Qt::DisplayRole: |
1458 | case Qt::EditRole: |
1459 | return t->completion().isStarted(); |
1460 | case Qt::ToolTipRole: |
1461 | if ( t->completion().isStarted() ) { |
1462 | return i18nc( "@info:tooltip" , "The task started at: %1" , KGlobal::locale()->formatDate( t->completion().startTime().date(), KLocale::LongDate ) ); |
1463 | } |
1464 | return i18nc( "@info:tooltip" , "The task is not started" ); |
1465 | case Qt::StatusTipRole: |
1466 | case Qt::WhatsThisRole: |
1467 | return QVariant(); |
1468 | } |
1469 | return QVariant(); |
1470 | } |
1471 | |
1472 | QVariant NodeModel::finishedTime( const Node *node, int role ) const |
1473 | { |
1474 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1475 | return QVariant(); |
1476 | } |
1477 | const Task *t = static_cast<const Task*>( node ); |
1478 | switch ( role ) { |
1479 | case Qt::DisplayRole: |
1480 | if ( t->completion().isFinished() ) { |
1481 | return KGlobal::locale()->formatDateTime( t->completion().finishTime() ); |
1482 | } |
1483 | break; |
1484 | case Qt::ToolTipRole: |
1485 | if ( t->completion().isFinished() ) { |
1486 | return i18nc( "@info:tooltip" , "Actual finish: %1" , KGlobal::locale()->formatDateTime( t->completion().finishTime(), KLocale::LongDate, KLocale::TimeZone ) ); |
1487 | } |
1488 | break; |
1489 | case Qt::EditRole: |
1490 | if ( t->completion().isFinished() ) { |
1491 | return t->completion().finishTime(); |
1492 | } |
1493 | break; |
1494 | case Qt::StatusTipRole: |
1495 | case Qt::WhatsThisRole: |
1496 | return QVariant(); |
1497 | } |
1498 | return QVariant(); |
1499 | } |
1500 | |
1501 | QVariant NodeModel::isFinished( const Node *node, int role ) const |
1502 | { |
1503 | if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { |
1504 | return QVariant(); |
1505 | } |
1506 | const Task *t = static_cast<const Task*>( node ); |
1507 | switch ( role ) { |
1508 | case Qt::DisplayRole: |
1509 | case Qt::EditRole: |
1510 | return t->completion().isFinished(); |
1511 | case Qt::ToolTipRole: |
1512 | if ( t->completion().isFinished() ) { |
1513 | return i18nc( "@info:tooltip" , "The task finished at: %1" , KGlobal::locale()->formatDate( t->completion().finishTime().date(), KLocale::LongDate ) ); |
1514 | } |
1515 | return i18nc( "@info:tooltip" , "The task is not finished" ); |
1516 | case Qt::StatusTipRole: |
1517 | case Qt::WhatsThisRole: |
1518 | return QVariant(); |
1519 | } |
1520 | return QVariant(); |
1521 | } |
1522 | |
1523 | QVariant NodeModel::plannedEffortTo( const Node *node, int role ) const |
1524 | { |
1525 | KLocale *l = KGlobal::locale(); |
1526 | switch ( role ) { |
1527 | case Qt::DisplayRole: |
1528 | return node->plannedEffortTo( m_now, id() ).format(); |
1529 | case Qt::ToolTipRole: |
1530 | return i18nc( "@info:tooltip" , "Planned effort until %1: %2" , l->formatDate( m_now ), node->plannedEffortTo( m_now, id() ).toString( Duration::Format_i18nHour ) ); |
1531 | case Qt::EditRole: |
1532 | return node->plannedEffortTo( m_now, id() ).toDouble( Duration::Unit_h ); |
1533 | case Role::DurationUnit: |
1534 | return static_cast<int>( Duration::Unit_h ); |
1535 | case Qt::StatusTipRole: |
1536 | case Qt::WhatsThisRole: |
1537 | return QVariant(); |
1538 | } |
1539 | return QVariant(); |
1540 | } |
1541 | |
1542 | QVariant NodeModel::actualEffortTo( const Node *node, int role ) const |
1543 | { |
1544 | KLocale *l = KGlobal::locale(); |
1545 | switch ( role ) { |
1546 | case Qt::DisplayRole: |
1547 | return node->actualEffortTo( m_now ).format(); |
1548 | case Qt::ToolTipRole: |
1549 | //kDebug(planDbg())<<m_now<<node; |
1550 | return i18nc( "@info:tooltip" , "Actual effort used up to %1: %2" , l->formatDate( m_now ), node->actualEffortTo( m_now ).toString( Duration::Format_i18nHour ) ); |
1551 | case Qt::EditRole: |
1552 | return node->actualEffortTo( m_now ).toDouble( Duration::Unit_h ); |
1553 | case Role::DurationUnit: |
1554 | return static_cast<int>( Duration::Unit_h ); |
1555 | case Qt::StatusTipRole: |
1556 | case Qt::WhatsThisRole: |
1557 | return QVariant(); |
1558 | } |
1559 | return QVariant(); |
1560 | } |
1561 | |
1562 | QVariant NodeModel::remainingEffort( const Node *node, int role ) const |
1563 | { |
1564 | switch ( role ) { |
1565 | case Qt::DisplayRole: { |
1566 | const Task *t = dynamic_cast<const Task*>( node ); |
1567 | if ( t ) { |
1568 | return t->completion().remainingEffort().format(); |
1569 | } |
1570 | break; |
1571 | } |
1572 | case Qt::ToolTipRole: { |
1573 | const Task *t = dynamic_cast<const Task*>( node ); |
1574 | if ( t ) { |
1575 | return i18nc( "@info:tooltip" , "Remaining effort: %1" , t->completion().remainingEffort().toString( Duration::Format_i18nHour ) ); |
1576 | } |
1577 | break; |
1578 | } |
1579 | case Qt::EditRole: { |
1580 | const Task *t = dynamic_cast<const Task*>( node ); |
1581 | return t->completion().remainingEffort().toDouble( Duration::Unit_h ); |
1582 | } |
1583 | case Role::DurationUnit: |
1584 | return static_cast<int>( Duration::Unit_h ); |
1585 | case Qt::StatusTipRole: |
1586 | case Qt::WhatsThisRole: |
1587 | return QVariant(); |
1588 | } |
1589 | return QVariant(); |
1590 | } |
1591 | |
1592 | QVariant NodeModel::plannedCostTo( const Node *node, int role ) const |
1593 | { |
1594 | KLocale *l = m_project->locale(); |
1595 | switch ( role ) { |
1596 | case Qt::DisplayRole: |
1597 | return l->formatMoney( node->plannedCostTo( m_now, id() ) ); |
1598 | case Qt::ToolTipRole: |
1599 | return i18nc( "@info:tooltip" , "Planned cost until %1: %2" , l->formatDate( m_now ), l->formatMoney( node->plannedCostTo( m_now, id() ) ) ); |
1600 | case Qt::EditRole: |
1601 | return node->plannedCostTo( m_now ); |
1602 | case Qt::StatusTipRole: |
1603 | case Qt::WhatsThisRole: |
1604 | return QVariant(); |
1605 | } |
1606 | return QVariant(); |
1607 | } |
1608 | |
1609 | QVariant NodeModel::actualCostTo( const Node *node, int role ) const |
1610 | { |
1611 | KLocale *l = m_project->locale(); |
1612 | switch ( role ) { |
1613 | case Qt::DisplayRole: |
1614 | return l->formatMoney( node->actualCostTo( id(), m_now ).cost() ); |
1615 | case Qt::ToolTipRole: |
1616 | return i18nc( "@info:tooltip" , "Actual cost until %1: %2" , l->formatDate( m_now ), l->formatMoney( node->actualCostTo( id(), m_now ).cost() ) ); |
1617 | case Qt::EditRole: |
1618 | return node->actualCostTo( id(), m_now ).cost(); |
1619 | case Qt::StatusTipRole: |
1620 | case Qt::WhatsThisRole: |
1621 | return QVariant(); |
1622 | } |
1623 | return QVariant(); |
1624 | } |
1625 | |
1626 | QVariant NodeModel::note( const Node *node, int role ) const |
1627 | { |
1628 | switch ( role ) { |
1629 | case Qt::DisplayRole: |
1630 | case Qt::EditRole: |
1631 | case Qt::ToolTipRole: |
1632 | if ( node->type() == Node::Type_Task ) { |
1633 | Node *n = const_cast<Node*>( node ); |
1634 | return static_cast<Task*>( n )->completion().note(); |
1635 | } |
1636 | break; |
1637 | case Qt::StatusTipRole: |
1638 | case Qt::WhatsThisRole: |
1639 | return QVariant(); |
1640 | } |
1641 | return QVariant(); |
1642 | } |
1643 | |
1644 | QVariant NodeModel::nodeSchedulingStatus( const Node *node, int role ) const |
1645 | { |
1646 | switch ( role ) { |
1647 | case Qt::DisplayRole: |
1648 | return node->schedulingStatus( id(), true ).value( 0 ); |
1649 | case Qt::EditRole: |
1650 | return node->schedulingStatus( id(), false ).value( 0 ); |
1651 | case Qt::ToolTipRole: |
1652 | return node->schedulingStatus( id(), true ).join( "\n" ); |
1653 | case Qt::StatusTipRole: |
1654 | case Qt::WhatsThisRole: |
1655 | return QVariant(); |
1656 | } |
1657 | return QVariant(); |
1658 | } |
1659 | |
1660 | QVariant NodeModel::resourceIsMissing( const Node *node, int role ) const |
1661 | { |
1662 | switch ( role ) { |
1663 | case Qt::DisplayRole: |
1664 | if ( node->resourceError( id() ) ) { |
1665 | return i18n( "Error" ); |
1666 | } |
1667 | break; |
1668 | case Qt::EditRole: |
1669 | return node->resourceError( id() ); |
1670 | case Qt::ToolTipRole: |
1671 | if ( node->resourceError( id() ) ) { |
1672 | return i18nc( "@info:tooltip" , "Resource allocation is expected when the task estimate type is <emphasis>Effort</emphasis>" ); |
1673 | } |
1674 | break; |
1675 | case Qt::StatusTipRole: |
1676 | case Qt::WhatsThisRole: |
1677 | return QVariant(); |
1678 | case Role::Foreground: { |
1679 | if ( ! m_project ) { |
1680 | break; |
1681 | } |
1682 | switch ( node->type() ) { |
1683 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1684 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1685 | default: |
1686 | break; |
1687 | } |
1688 | } |
1689 | } |
1690 | return QVariant(); |
1691 | } |
1692 | |
1693 | QVariant NodeModel::resourceIsOverbooked( const Node *node, int role ) const |
1694 | { |
1695 | switch ( role ) { |
1696 | case Qt::DisplayRole: |
1697 | if ( node->resourceOverbooked( id() ) ) { |
1698 | return i18n( "Error" ); |
1699 | } |
1700 | break; |
1701 | case Qt::EditRole: |
1702 | return node->resourceOverbooked( id() ); |
1703 | case Qt::ToolTipRole: |
1704 | if ( node->resourceOverbooked( id() ) ) { |
1705 | return i18nc( "@info:tooltip" , "A resource has been overbooked" ); |
1706 | } |
1707 | break; |
1708 | case Qt::StatusTipRole: |
1709 | case Qt::WhatsThisRole: |
1710 | return QVariant(); |
1711 | case Role::Foreground: { |
1712 | if ( ! m_project ) { |
1713 | break; |
1714 | } |
1715 | switch ( node->type() ) { |
1716 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1717 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1718 | default: |
1719 | break; |
1720 | } |
1721 | } |
1722 | } |
1723 | return QVariant(); |
1724 | } |
1725 | |
1726 | QVariant NodeModel::resourceIsNotAvailable( const Node *node, int role ) const |
1727 | { |
1728 | switch ( role ) { |
1729 | case Qt::DisplayRole: |
1730 | if ( node->resourceNotAvailable( id() ) ) { |
1731 | return i18n( "Error" ); |
1732 | } |
1733 | break; |
1734 | case Qt::EditRole: |
1735 | return node->resourceNotAvailable( id() ); |
1736 | case Qt::ToolTipRole: |
1737 | if ( node->resourceNotAvailable( id() ) ) { |
1738 | return i18nc( "@info:tooltip" , "No resource is available for this task" ); |
1739 | } |
1740 | break; |
1741 | case Qt::StatusTipRole: |
1742 | case Qt::WhatsThisRole: |
1743 | return QVariant(); |
1744 | case Role::Foreground: { |
1745 | if ( ! m_project ) { |
1746 | break; |
1747 | } |
1748 | switch ( node->type() ) { |
1749 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1750 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1751 | default: |
1752 | break; |
1753 | } |
1754 | } |
1755 | } |
1756 | return QVariant(); |
1757 | } |
1758 | |
1759 | QVariant NodeModel::schedulingConstraintsError( const Node *node, int role ) const |
1760 | { |
1761 | switch ( role ) { |
1762 | case Qt::DisplayRole: |
1763 | if ( node->constraintError( id() ) ) { |
1764 | return i18n( "Error" ); |
1765 | } |
1766 | break; |
1767 | case Qt::EditRole: |
1768 | return node->constraintError( id() ); |
1769 | case Qt::ToolTipRole: |
1770 | if ( node->constraintError( id() ) ) { |
1771 | return i18nc( "@info:tooltip" , "Failed to comply with a timing constraint" ); |
1772 | } |
1773 | break; |
1774 | case Qt::StatusTipRole: |
1775 | case Qt::WhatsThisRole: |
1776 | return QVariant(); |
1777 | case Role::Foreground: { |
1778 | if ( ! m_project ) { |
1779 | break; |
1780 | } |
1781 | switch ( node->type() ) { |
1782 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1783 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1784 | default: |
1785 | break; |
1786 | } |
1787 | } |
1788 | } |
1789 | return QVariant(); |
1790 | } |
1791 | |
1792 | QVariant NodeModel::nodeIsNotScheduled( const Node *node, int role ) const |
1793 | { |
1794 | switch ( role ) { |
1795 | case Qt::DisplayRole: |
1796 | if ( node->notScheduled( id() ) ) { |
1797 | return i18n( "Error" ); |
1798 | } |
1799 | break; |
1800 | case Qt::EditRole: |
1801 | return node->notScheduled( id() ); |
1802 | case Qt::ToolTipRole: |
1803 | if ( node->notScheduled( id() ) ) { |
1804 | return i18nc( "@info:tooltip" , "This task has not been scheduled" ); |
1805 | } |
1806 | break; |
1807 | case Qt::StatusTipRole: |
1808 | case Qt::WhatsThisRole: |
1809 | return QVariant(); |
1810 | case Role::Foreground: { |
1811 | if ( ! m_project ) { |
1812 | break; |
1813 | } |
1814 | switch ( node->type() ) { |
1815 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1816 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1817 | default: |
1818 | break; |
1819 | } |
1820 | } |
1821 | } |
1822 | return QVariant(); |
1823 | } |
1824 | |
1825 | QVariant NodeModel::effortNotMet( const Node *node, int role ) const |
1826 | { |
1827 | switch ( role ) { |
1828 | case Qt::DisplayRole: |
1829 | if ( node->effortMetError( id() ) ) { |
1830 | return i18n( "Error" ); |
1831 | } |
1832 | break; |
1833 | case Qt::EditRole: |
1834 | return node->effortMetError( id() ); |
1835 | case Qt::ToolTipRole: |
1836 | if ( node->effortMetError( id() ) ) { |
1837 | return i18nc( "@info:tooltip" , "The assigned resources cannot deliver the required estimated effort" ); |
1838 | } |
1839 | break; |
1840 | case Qt::StatusTipRole: |
1841 | case Qt::WhatsThisRole: |
1842 | return QVariant(); |
1843 | case Role::Foreground: { |
1844 | if ( ! m_project ) { |
1845 | break; |
1846 | } |
1847 | switch ( node->type() ) { |
1848 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1849 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1850 | default: |
1851 | break; |
1852 | } |
1853 | } |
1854 | } |
1855 | return QVariant(); |
1856 | } |
1857 | |
1858 | QVariant NodeModel::schedulingError( const Node *node, int role ) const |
1859 | { |
1860 | switch ( role ) { |
1861 | case Qt::DisplayRole: |
1862 | if ( node->schedulingError( id() ) ) { |
1863 | return i18n( "Error" ); |
1864 | } |
1865 | break; |
1866 | case Qt::EditRole: |
1867 | return node->schedulingError( id() ); |
1868 | case Qt::ToolTipRole: |
1869 | if ( node->schedulingError( id() ) ) { |
1870 | return i18nc( "@info:tooltip" , "Scheduling error" ); |
1871 | } |
1872 | break; |
1873 | case Qt::StatusTipRole: |
1874 | case Qt::WhatsThisRole: |
1875 | return QVariant(); |
1876 | case Role::Foreground: { |
1877 | if ( ! m_project ) { |
1878 | break; |
1879 | } |
1880 | switch ( node->type() ) { |
1881 | case Node::Type_Task: return m_project->config().taskErrorColor(); |
1882 | case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); |
1883 | default: |
1884 | break; |
1885 | } |
1886 | } |
1887 | } |
1888 | return QVariant(); |
1889 | } |
1890 | |
1891 | QVariant NodeModel::wbsCode( const Node *node, int role ) const |
1892 | { |
1893 | switch ( role ) { |
1894 | case Qt::DisplayRole: |
1895 | case Qt::EditRole: |
1896 | return node->wbsCode(); |
1897 | case Qt::ToolTipRole: |
1898 | return i18nc( "@info:tooltip" , "Work breakdown structure code: %1" , node->wbsCode() ); |
1899 | case Qt::StatusTipRole: |
1900 | case Qt::WhatsThisRole: |
1901 | return QVariant(); |
1902 | } |
1903 | return QVariant(); |
1904 | } |
1905 | |
1906 | QVariant NodeModel::nodeLevel( const Node *node, int role ) const |
1907 | { |
1908 | switch ( role ) { |
1909 | case Qt::DisplayRole: |
1910 | case Qt::EditRole: |
1911 | return node->level(); |
1912 | case Qt::ToolTipRole: |
1913 | return i18nc( "@info:tooltip" , "Task level: %1" , node->level() ); |
1914 | case Qt::StatusTipRole: |
1915 | case Qt::WhatsThisRole: |
1916 | return QVariant(); |
1917 | } |
1918 | return QVariant(); |
1919 | } |
1920 | |
1921 | QVariant NodeModel::nodeBCWS( const Node *node, int role ) const |
1922 | { |
1923 | switch ( role ) { |
1924 | case Qt::DisplayRole: |
1925 | return m_project->locale()->formatMoney( node->bcws( m_now, id() ), QString(), 0 ); |
1926 | case Qt::EditRole: |
1927 | return node->bcws( m_now, id() ); |
1928 | case Qt::ToolTipRole: |
1929 | return i18nc( "@info:tooltip" , "Budgeted Cost of Work Scheduled at %1: %2" , m_now.toString(), m_project->locale()->formatMoney( node->bcws( m_now, id() ), QString(), 0 ) ); |
1930 | case Qt::StatusTipRole: |
1931 | case Qt::WhatsThisRole: |
1932 | return QVariant(); |
1933 | } |
1934 | return QVariant(); |
1935 | } |
1936 | |
1937 | QVariant NodeModel::nodeBCWP( const Node *node, int role ) const |
1938 | { |
1939 | switch ( role ) { |
1940 | case Qt::DisplayRole: |
1941 | return m_project->locale()->formatMoney( node->bcwp( id() ), QString(), 0 ); |
1942 | case Qt::EditRole: |
1943 | return node->bcwp( id() ); |
1944 | case Qt::ToolTipRole: |
1945 | return i18nc( "@info:tooltip" , "Budgeted Cost of Work Performed at %1: %2" , m_now.toString(), m_project->locale()->formatMoney( node->bcwp( id() ), QString(), 0 ) ); |
1946 | case Qt::StatusTipRole: |
1947 | case Qt::WhatsThisRole: |
1948 | return QVariant(); |
1949 | } |
1950 | return QVariant(); |
1951 | } |
1952 | |
1953 | QVariant NodeModel::nodeACWP( const Node *node, int role ) const |
1954 | { |
1955 | switch ( role ) { |
1956 | case Qt::DisplayRole: |
1957 | return m_project->locale()->formatMoney( node->acwp( m_now, id() ).cost(), QString(), 0 ); |
1958 | case Qt::EditRole: |
1959 | return node->acwp( m_now, id() ).cost(); |
1960 | case Qt::ToolTipRole: |
1961 | return i18nc( "@info:tooltip" , "Actual Cost of Work Performed at %1: %2" , m_now.toString(), m_project->locale()->formatMoney( node->acwp( m_now, id() ).cost() ) ); |
1962 | case Qt::StatusTipRole: |
1963 | case Qt::WhatsThisRole: |
1964 | return QVariant(); |
1965 | } |
1966 | return QVariant(); |
1967 | } |
1968 | |
1969 | QVariant NodeModel::nodePerformanceIndex( const Node *node, int role ) const |
1970 | { |
1971 | switch ( role ) { |
1972 | case Qt::DisplayRole: |
1973 | return KGlobal::locale()->formatNumber( node->schedulePerformanceIndex( m_now, id() ), 2 ); |
1974 | case Qt::EditRole: |
1975 | return node->schedulePerformanceIndex( m_now, id() ); |
1976 | case Qt::ToolTipRole: |
1977 | return i18nc( "@info:tooltip" , "Schedule Performance Index at %1: %2" , m_now.toString(), KGlobal::locale()->formatNumber( node->schedulePerformanceIndex( m_now, id() ), 2 ) ); |
1978 | case Qt::StatusTipRole: |
1979 | case Qt::WhatsThisRole: |
1980 | return QVariant(); |
1981 | case Qt::ForegroundRole: |
1982 | return node->schedulePerformanceIndex( m_now, id() ) < 1.0 ? Qt::red : Qt::black; |
1983 | } |
1984 | return QVariant(); |
1985 | } |
1986 | |
1987 | QVariant NodeModel::nodeIsCritical( const Node *node, int role ) const |
1988 | { |
1989 | switch ( role ) { |
1990 | case Qt::DisplayRole: |
1991 | case Qt::EditRole: |
1992 | return node->isCritical( id() ); |
1993 | case Qt::ToolTipRole: |
1994 | case Qt::StatusTipRole: |
1995 | case Qt::WhatsThisRole: |
1996 | return QVariant(); |
1997 | case Role::Foreground: { |
1998 | if ( ! m_project ) { |
1999 | break; |
2000 | } |
2001 | switch ( node->type() ) { |
2002 | case Node::Type_Task: return m_project->config().taskNormalColor(); |
2003 | case Node::Type_Milestone: return m_project->config().milestoneNormalColor(); |
2004 | default: |
2005 | break; |
2006 | } |
2007 | } |
2008 | } |
2009 | return QVariant(); |
2010 | } |
2011 | |
2012 | QVariant NodeModel::nodeInCriticalPath( const Node *node, int role ) const |
2013 | { |
2014 | switch ( role ) { |
2015 | case Qt::DisplayRole: |
2016 | case Qt::EditRole: |
2017 | return node->inCriticalPath( id() ); |
2018 | case Qt::ToolTipRole: |
2019 | case Qt::StatusTipRole: |
2020 | case Qt::WhatsThisRole: |
2021 | return QVariant(); |
2022 | case Role::Foreground: { |
2023 | if ( ! m_project ) { |
2024 | break; |
2025 | } |
2026 | switch ( node->type() ) { |
2027 | case Node::Type_Task: return m_project->config().taskNormalColor(); |
2028 | case Node::Type_Milestone: return m_project->config().milestoneNormalColor(); |
2029 | default: |
2030 | break; |
2031 | } |
2032 | } |
2033 | } |
2034 | return QVariant(); |
2035 | } |
2036 | |
2037 | QVariant NodeModel::wpOwnerName( const Node *node, int role ) const |
2038 | { |
2039 | switch ( role ) { |
2040 | case Qt::DisplayRole: |
2041 | case Qt::EditRole: { |
2042 | const Task *t = dynamic_cast<const Task*>( node ); |
2043 | if ( t == 0 ) { |
2044 | return QVariant(); |
2045 | } |
2046 | if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { |
2047 | return i18nc( "Not available" , "NA" ); |
2048 | } |
2049 | return t->wpOwnerName(); |
2050 | } |
2051 | case Qt::ToolTipRole: { |
2052 | const Task *task = dynamic_cast<const Task*>( node ); |
2053 | if ( task == 0 ) { |
2054 | return QVariant(); |
2055 | } |
2056 | int sts = task->wpTransmitionStatus(); |
2057 | QString t = wpTransmitionTime( node, Qt::DisplayRole ).toString(); |
2058 | if ( sts == WorkPackage::TS_Send ) { |
2059 | return i18nc( "@info:tooltip" , "Latest work package sent to %1 at %2" , static_cast<const Task*>( node )->wpOwnerName(), t ); |
2060 | } |
2061 | if ( sts == WorkPackage::TS_Receive ) { |
2062 | return i18nc( "@info:tooltip" , "Latest work package received from %1 at %2" , static_cast<const Task*>( node )->wpOwnerName(), t ); |
2063 | } |
2064 | return i18nc( "@info:tooltip" , "Not available" ); |
2065 | } |
2066 | case Qt::StatusTipRole: |
2067 | case Qt::WhatsThisRole: |
2068 | return QVariant(); |
2069 | } |
2070 | return QVariant(); |
2071 | } |
2072 | |
2073 | QVariant NodeModel::wpTransmitionStatus( const Node *node, int role ) const |
2074 | { |
2075 | switch ( role ) { |
2076 | case Qt::DisplayRole: { |
2077 | const Task *t = dynamic_cast<const Task*>( node ); |
2078 | if ( t == 0 ) { |
2079 | return QVariant(); |
2080 | } |
2081 | if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { |
2082 | return i18nc( "Not available" , "NA" ); |
2083 | } |
2084 | return WorkPackage::transmitionStatusToString( t->wpTransmitionStatus(), true ); |
2085 | } |
2086 | case Qt::EditRole: { |
2087 | const Task *t = dynamic_cast<const Task*>( node ); |
2088 | if ( t == 0 ) { |
2089 | return QVariant(); |
2090 | } |
2091 | return WorkPackage::transmitionStatusToString( t->wpTransmitionStatus(), false ); |
2092 | } |
2093 | case Qt::ToolTipRole: |
2094 | case Qt::StatusTipRole: |
2095 | case Qt::WhatsThisRole: |
2096 | return QVariant(); |
2097 | } |
2098 | return QVariant(); |
2099 | } |
2100 | |
2101 | QVariant NodeModel::wpTransmitionTime( const Node *node, int role ) const |
2102 | { |
2103 | switch ( role ) { |
2104 | case Qt::DisplayRole: |
2105 | case Qt::EditRole: { |
2106 | const Task *t = dynamic_cast<const Task*>( node ); |
2107 | if ( t == 0 ) { |
2108 | return QVariant(); |
2109 | } |
2110 | if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { |
2111 | return i18nc( "Not available" , "NA" ); |
2112 | } |
2113 | return KGlobal::locale()->formatDateTime( t->wpTransmitionTime() ); |
2114 | } |
2115 | case Qt::ToolTipRole: { |
2116 | const Task *task = dynamic_cast<const Task*>( node ); |
2117 | if ( task == 0 ) { |
2118 | return QVariant(); |
2119 | } |
2120 | int sts = task->wpTransmitionStatus(); |
2121 | QString t = wpTransmitionTime( node, Qt::DisplayRole ).toString(); |
2122 | if ( sts == WorkPackage::TS_Send ) { |
2123 | return i18nc( "@info:tooltip" , "Latest work package sent: %1" , t ); |
2124 | } |
2125 | if ( sts == WorkPackage::TS_Receive ) { |
2126 | return i18nc( "@info:tooltip" , "Latest work package received: %1" , t ); |
2127 | } |
2128 | return i18nc( "@info:tooltip" , "Not available" ); |
2129 | } |
2130 | case Qt::StatusTipRole: |
2131 | case Qt::WhatsThisRole: |
2132 | return QVariant(); |
2133 | } |
2134 | return QVariant(); |
2135 | } |
2136 | |
2137 | QVariant NodeModel::data( const Node *n, int property, int role ) const |
2138 | { |
2139 | QVariant result; |
2140 | switch ( property ) { |
2141 | // Edited by user |
2142 | case NodeName: result = name( n, role ); break; |
2143 | case NodeType: result = type( n, role ); break; |
2144 | case NodeResponsible: result = leader( n, role ); break; |
2145 | case NodeAllocation: result = allocation( n, role ); break; |
2146 | case NodeEstimateType: result = estimateType( n, role ); break; |
2147 | case NodeEstimateCalendar: result = estimateCalendar( n, role ); break; |
2148 | case NodeEstimate: result = estimate( n, role ); break; |
2149 | case NodeOptimisticRatio: result = optimisticRatio( n, role ); break; |
2150 | case NodePessimisticRatio: result = pessimisticRatio( n, role ); break; |
2151 | case NodeRisk: result = riskType( n, role ); break; |
2152 | case NodeConstraint: result = constraint( n, role ); break; |
2153 | case NodeConstraintStart: result = constraintStartTime( n, role ); break; |
2154 | case NodeConstraintEnd: result = constraintEndTime( n, role ); break; |
2155 | case NodeRunningAccount: result = runningAccount( n, role ); break; |
2156 | case NodeStartupAccount: result = startupAccount( n, role ); break; |
2157 | case NodeStartupCost: result = startupCost( n, role ); break; |
2158 | case NodeShutdownAccount: result = shutdownAccount( n, role ); break; |
2159 | case NodeShutdownCost: result = shutdownCost( n, role ); break; |
2160 | case NodeDescription: result = description( n, role ); break; |
2161 | |
2162 | // Based on edited values |
2163 | case NodeExpected: result = pertExpected( n->estimate(), role ); break; |
2164 | case NodeVarianceEstimate: result = varianceEstimate( n->estimate(), role ); break; |
2165 | case NodeOptimistic: result = optimisticEstimate( n->estimate(), role ); break; |
2166 | case NodePessimistic: result = pessimisticEstimate( n->estimate(), role ); break; |
2167 | |
2168 | // After scheduling |
2169 | case NodeStartTime: result = startTime( n, role ); break; |
2170 | case NodeEndTime: result = endTime( n, role ); break; |
2171 | case NodeEarlyStart: result = earlyStart( n, role ); break; |
2172 | case NodeEarlyFinish: result = earlyFinish( n, role ); break; |
2173 | case NodeLateStart: result = lateStart( n, role ); break; |
2174 | case NodeLateFinish: result = lateFinish( n, role ); break; |
2175 | case NodePositiveFloat: result = positiveFloat( n, role ); break; |
2176 | case NodeFreeFloat: result = freeFloat( n, role ); break; |
2177 | case NodeNegativeFloat: result = negativeFloat( n, role ); break; |
2178 | case NodeStartFloat: result = startFloat( n, role ); break; |
2179 | case NodeFinishFloat: result = finishFloat( n, role ); break; |
2180 | case NodeAssignments: result = assignedResources( n, role ); break; |
2181 | |
2182 | // Based on scheduled values |
2183 | case NodeDuration: result = duration( n, role ); break; |
2184 | case NodeVarianceDuration: result = varianceDuration( n, role ); break; |
2185 | case NodeOptimisticDuration: result = optimisticDuration( n, role ); break; |
2186 | case NodePessimisticDuration: result = pessimisticDuration( n, role ); break; |
2187 | |
2188 | // Completion |
2189 | case NodeStatus: result = status( n, role ); break; |
2190 | case NodeCompleted: result = completed( n, role ); break; |
2191 | case NodePlannedEffort: result = plannedEffortTo( n, role ); break; |
2192 | case NodeActualEffort: result = actualEffortTo( n, role ); break; |
2193 | case NodeRemainingEffort: result = remainingEffort( n, role ); break; |
2194 | case NodePlannedCost: result = plannedCostTo( n, role ); break; |
2195 | case NodeActualCost: result = actualCostTo( n, role ); break; |
2196 | case NodeActualStart: result = startedTime( n, role ); break; |
2197 | case NodeStarted: result = isStarted( n, role ); break; |
2198 | case NodeActualFinish: result = finishedTime( n, role ); break; |
2199 | case NodeFinished: result = isFinished( n, role ); break; |
2200 | case NodeStatusNote: result = note( n, role ); break; |
2201 | |
2202 | // Scheduling errors |
2203 | case NodeSchedulingStatus: result = nodeSchedulingStatus( n, role ); break; |
2204 | case NodeNotScheduled: result = nodeIsNotScheduled( n, role ); break; |
2205 | case NodeAssignmentMissing: result = resourceIsMissing( n, role ); break; |
2206 | case NodeResourceOverbooked: result = resourceIsOverbooked( n, role ); break; |
2207 | case NodeResourceUnavailable: result = resourceIsNotAvailable( n, role ); break; |
2208 | case NodeConstraintsError: result = schedulingConstraintsError( n, role ); break; |
2209 | case NodeEffortNotMet: result = effortNotMet( n, role ); break; |
2210 | case NodeSchedulingError: result = schedulingError( n, role ); break; |
2211 | |
2212 | case NodeWBSCode: result = wbsCode( n, role ); break; |
2213 | case NodeLevel: result = nodeLevel( n, role ); break; |
2214 | |
2215 | // Performance |
2216 | case NodeBCWS: result = nodeBCWS( n, role ); break; |
2217 | case NodeBCWP: result = nodeBCWP( n, role ); break; |
2218 | case NodeACWP: result = nodeACWP( n, role ); break; |
2219 | case NodePerformanceIndex: result = nodePerformanceIndex( n, role ); break; |
2220 | case NodeCritical: result = nodeIsCritical( n, role ); break; |
2221 | case NodeCriticalPath: result = nodeInCriticalPath( n, role ); break; |
2222 | |
2223 | case WPOwnerName: result = wpOwnerName( n, role ); break; |
2224 | case WPTransmitionStatus: result = wpTransmitionStatus( n, role ); break; |
2225 | case WPTransmitionTime: result = wpTransmitionTime( n, role ); break; |
2226 | |
2227 | default: |
2228 | //kDebug(planDbg())<<"Invalid property number: "<<property;; |
2229 | return result; |
2230 | } |
2231 | return result; |
2232 | } |
2233 | |
2234 | int NodeModel::propertyCount() const |
2235 | { |
2236 | return columnMap().keyCount(); |
2237 | } |
2238 | |
2239 | KUndo2Command *NodeModel::setData( Node *node, int property, const QVariant & value, int role ) |
2240 | { |
2241 | switch ( property ) { |
2242 | case NodeModel::NodeName: return setName( node, value, role ); |
2243 | case NodeModel::NodeType: return setType( node, value, role ); |
2244 | case NodeModel::NodeResponsible: return setLeader( node, value, role ); |
2245 | case NodeModel::NodeAllocation: return setAllocation( node, value, role ); |
2246 | case NodeModel::NodeEstimateType: return setEstimateType( node, value, role ); |
2247 | case NodeModel::NodeEstimateCalendar: return setEstimateCalendar( node, value, role ); |
2248 | case NodeModel::NodeEstimate: return setEstimate( node, value, role ); |
2249 | case NodeModel::NodeOptimisticRatio: return setOptimisticRatio( node, value, role ); |
2250 | case NodeModel::NodePessimisticRatio: return setPessimisticRatio( node, value, role ); |
2251 | case NodeModel::NodeRisk: return setRiskType( node, value, role ); |
2252 | case NodeModel::NodeConstraint: return setConstraint( node, value, role ); |
2253 | case NodeModel::NodeConstraintStart: return setConstraintStartTime( node, value, role ); |
2254 | case NodeModel::NodeConstraintEnd: return setConstraintEndTime( node, value, role ); |
2255 | case NodeModel::NodeRunningAccount: return setRunningAccount( node, value, role ); |
2256 | case NodeModel::NodeStartupAccount: return setStartupAccount( node, value, role ); |
2257 | case NodeModel::NodeStartupCost: return setStartupCost( node, value, role ); |
2258 | case NodeModel::NodeShutdownAccount: return setShutdownAccount( node, value, role ); |
2259 | case NodeModel::NodeShutdownCost: return setShutdownCost( node, value, role ); |
2260 | case NodeModel::NodeDescription: return setDescription( node, value, role ); |
2261 | case NodeModel::NodeCompleted: return setCompletion( node, value, role ); |
2262 | case NodeModel::NodeActualEffort: return setActualEffort( node, value, role ); |
2263 | case NodeModel::NodeRemainingEffort: return setRemainingEffort( node, value, role ); |
2264 | case NodeModel::NodeActualStart: return setStartedTime( node, value, role ); |
2265 | case NodeModel::NodeActualFinish: return setFinishedTime( node, value, role ); |
2266 | default: |
2267 | qWarning("data: invalid display value column %d" , property); |
2268 | return 0; |
2269 | } |
2270 | return 0; |
2271 | } |
2272 | |
2273 | QVariant NodeModel::( int section, int role ) |
2274 | { |
2275 | if ( role == Qt::DisplayRole ) { |
2276 | switch ( section ) { |
2277 | case NodeName: return i18nc( "@title:column" , "Name" ); |
2278 | case NodeType: return i18nc( "@title:column" , "Type" ); |
2279 | case NodeResponsible: return i18nc( "@title:column" , "Responsible" ); |
2280 | case NodeAllocation: return i18nc( "@title:column" , "Allocation" ); |
2281 | case NodeEstimateType: return i18nc( "@title:column" , "Estimate Type" ); |
2282 | case NodeEstimateCalendar: return i18nc( "@title:column" , "Calendar" ); |
2283 | case NodeEstimate: return i18nc( "@title:column" , "Estimate" ); |
2284 | case NodeOptimisticRatio: return i18nc( "@title:column" , "Optimistic" ); // Ratio |
2285 | case NodePessimisticRatio: return i18nc( "@title:column" , "Pessimistic" ); // Ratio |
2286 | case NodeRisk: return i18nc( "@title:column" , "Risk" ); |
2287 | case NodeConstraint: return i18nc( "@title:column" , "Constraint" ); |
2288 | case NodeConstraintStart: return i18nc( "@title:column" , "Constraint Start" ); |
2289 | case NodeConstraintEnd: return i18nc( "@title:column" , "Constraint End" ); |
2290 | case NodeRunningAccount: return i18nc( "@title:column" , "Running Account" ); |
2291 | case NodeStartupAccount: return i18nc( "@title:column" , "Startup Account" ); |
2292 | case NodeStartupCost: return i18nc( "@title:column" , "Startup Cost" ); |
2293 | case NodeShutdownAccount: return i18nc( "@title:column" , "Shutdown Account" ); |
2294 | case NodeShutdownCost: return i18nc( "@title:column" , "Shutdown Cost" ); |
2295 | case NodeDescription: return i18nc( "@title:column" , "Description" ); |
2296 | |
2297 | // Based on edited values |
2298 | case NodeExpected: return i18nc( "@title:column" , "Expected" ); |
2299 | case NodeVarianceEstimate: return i18nc( "@title:column" , "Variance (Est)" ); |
2300 | case NodeOptimistic: return i18nc( "@title:column" , "Optimistic" ); |
2301 | case NodePessimistic: return i18nc( "@title:column" , "Pessimistic" ); |
2302 | |
2303 | // After scheduling |
2304 | case NodeStartTime: return i18nc( "@title:column" , "Start Time" ); |
2305 | case NodeEndTime: return i18nc( "@title:column" , "End Time" ); |
2306 | case NodeEarlyStart: return i18nc( "@title:column" , "Early Start" ); |
2307 | case NodeEarlyFinish: return i18nc( "@title:column" , "Early Finish" ); |
2308 | case NodeLateStart: return i18nc( "@title:column" , "Late Start" ); |
2309 | case NodeLateFinish: return i18nc( "@title:column" , "Late Finish" ); |
2310 | case NodePositiveFloat: return i18nc( "@title:column" , "Positive Float" ); |
2311 | case NodeFreeFloat: return i18nc( "@title:column" , "Free Float" ); |
2312 | case NodeNegativeFloat: return i18nc( "@title:column" , "Negative Float" ); |
2313 | case NodeStartFloat: return i18nc( "@title:column" , "Start Float" ); |
2314 | case NodeFinishFloat: return i18nc( "@title:column" , "Finish Float" ); |
2315 | case NodeAssignments: return i18nc( "@title:column" , "Assignments" ); |
2316 | |
2317 | // Based on scheduled values |
2318 | case NodeDuration: return i18nc( "@title:column" , "Duration" ); |
2319 | case NodeVarianceDuration: return i18nc( "@title:column" , "Variance (Dur)" ); |
2320 | case NodeOptimisticDuration: return i18nc( "@title:column" , "Optimistic (Dur)" ); |
2321 | case NodePessimisticDuration: return i18nc( "@title:column" , "Pessimistic (Dur)" ); |
2322 | |
2323 | // Completion |
2324 | case NodeStatus: return i18nc( "@title:column" , "Status" ); |
2325 | // xgettext: no-c-format |
2326 | case NodeCompleted: return i18nc( "@title:column" , "% Completed" ); |
2327 | case NodePlannedEffort: return i18nc( "@title:column" , "Planned Effort" ); |
2328 | case NodeActualEffort: return i18nc( "@title:column" , "Actual Effort" ); |
2329 | case NodeRemainingEffort: return i18nc( "@title:column" , "Remaining Effort" ); |
2330 | case NodePlannedCost: return i18nc( "@title:column" , "Planned Cost" ); |
2331 | case NodeActualCost: return i18nc( "@title:column" , "Actual Cost" ); |
2332 | case NodeActualStart: return i18nc( "@title:column" , "Actual Start" ); |
2333 | case NodeStarted: return i18nc( "@title:column" , "Started" ); |
2334 | case NodeActualFinish: return i18nc( "@title:column" , "Actual Finish" ); |
2335 | case NodeFinished: return i18nc( "@title:column" , "Finished" ); |
2336 | case NodeStatusNote: return i18nc( "@title:column" , "Status Note" ); |
2337 | |
2338 | // Scheduling errors |
2339 | case NodeSchedulingStatus: return i18nc( "@title:column" , "Scheduling Status" ); |
2340 | case NodeNotScheduled: return i18nc( "@title:column" , "Not Scheduled" ); |
2341 | case NodeAssignmentMissing: return i18nc( "@title:column" , "Assignment Missing" ); |
2342 | case NodeResourceOverbooked: return i18nc( "@title:column" , "Resource Overbooked" ); |
2343 | case NodeResourceUnavailable: return i18nc( "@title:column" , "Resource Unavailable" ); |
2344 | case NodeConstraintsError: return i18nc( "@title:column" , "Constraints Error" ); |
2345 | case NodeEffortNotMet: return i18nc( "@title:column" , "Effort Not Met" ); |
2346 | case NodeSchedulingError: return i18nc( "@title:column" , "Scheduling Error" ); |
2347 | |
2348 | case NodeWBSCode: return i18nc( "@title:column" , "WBS Code" ); |
2349 | case NodeLevel: return i18nc( "@title:column Node level" , "Level" ); |
2350 | |
2351 | // Performance |
2352 | case NodeBCWS: return i18nc( "@title:column Budgeted Cost of Work Scheduled" , "BCWS" ); |
2353 | case NodeBCWP: return i18nc( "@title:column Budgeted Cost of Work Performed" , "BCWP" ); |
2354 | case NodeACWP: return i18nc( "@title:column Actual Cost of Work Performed" , "ACWP" ); |
2355 | case NodePerformanceIndex: return i18nc( "@title:column Schedule Performance Index" , "SPI" ); |
2356 | case NodeCritical: return i18nc( "@title:column" , "Critical" ); |
2357 | case NodeCriticalPath: return i18nc( "@title:column" , "Critical Path" ); |
2358 | |
2359 | // Work package handling |
2360 | case WPOwnerName: return i18nc( "@title:column" , "Owner" ); |
2361 | case WPTransmitionStatus: return i18nc( "@title:column" , "Status" ); |
2362 | case WPTransmitionTime: return i18nc( "@title:column" , "Time" ); |
2363 | |
2364 | default: return QVariant(); |
2365 | } |
2366 | } |
2367 | if ( role == Qt::ToolTipRole ) { |
2368 | switch ( section ) { |
2369 | case NodeName: return ToolTip::nodeName(); |
2370 | case NodeType: return ToolTip::nodeType(); |
2371 | case NodeResponsible: return ToolTip::nodeResponsible(); |
2372 | case NodeAllocation: return ToolTip::allocation(); |
2373 | case NodeEstimateType: return ToolTip::estimateType(); |
2374 | case NodeEstimateCalendar: return ToolTip::estimateCalendar(); |
2375 | case NodeEstimate: return ToolTip::estimate(); |
2376 | case NodeOptimisticRatio: return ToolTip::optimisticRatio(); |
2377 | case NodePessimisticRatio: return ToolTip::pessimisticRatio(); |
2378 | case NodeRisk: return ToolTip::riskType(); |
2379 | case NodeConstraint: return ToolTip::nodeConstraint(); |
2380 | case NodeConstraintStart: return ToolTip::nodeConstraintStart(); |
2381 | case NodeConstraintEnd: return ToolTip::nodeConstraintEnd(); |
2382 | case NodeRunningAccount: return ToolTip::nodeRunningAccount(); |
2383 | case NodeStartupAccount: return ToolTip::nodeStartupAccount(); |
2384 | case NodeStartupCost: return ToolTip::nodeStartupCost(); |
2385 | case NodeShutdownAccount: return ToolTip::nodeShutdownAccount(); |
2386 | case NodeShutdownCost: return ToolTip::nodeShutdownCost(); |
2387 | case NodeDescription: return ToolTip::nodeDescription(); |
2388 | |
2389 | // Based on edited values |
2390 | case NodeExpected: return ToolTip::estimateExpected(); |
2391 | case NodeVarianceEstimate: return ToolTip::estimateVariance(); |
2392 | case NodeOptimistic: return ToolTip::estimateOptimistic(); |
2393 | case NodePessimistic: return ToolTip::estimatePessimistic(); |
2394 | |
2395 | // After scheduling |
2396 | case NodeStartTime: return ToolTip::nodeStartTime(); |
2397 | case NodeEndTime: return ToolTip::nodeEndTime(); |
2398 | case NodeEarlyStart: return ToolTip::nodeEarlyStart(); |
2399 | case NodeEarlyFinish: return ToolTip::nodeEarlyFinish(); |
2400 | case NodeLateStart: return ToolTip::nodeLateStart(); |
2401 | case NodeLateFinish: return ToolTip::nodeLateFinish(); |
2402 | case NodePositiveFloat: return ToolTip::nodePositiveFloat(); |
2403 | case NodeFreeFloat: return ToolTip::nodeFreeFloat(); |
2404 | case NodeNegativeFloat: return ToolTip::nodeNegativeFloat(); |
2405 | case NodeStartFloat: return ToolTip::nodeStartFloat(); |
2406 | case NodeFinishFloat: return ToolTip::nodeFinishFloat(); |
2407 | case NodeAssignments: return ToolTip::nodeAssignment(); |
2408 | |
2409 | // Based on scheduled values |
2410 | case NodeDuration: return ToolTip::nodeDuration(); |
2411 | case NodeVarianceDuration: return ToolTip::nodeVarianceDuration(); |
2412 | case NodeOptimisticDuration: return ToolTip::nodeOptimisticDuration(); |
2413 | case NodePessimisticDuration: return ToolTip::nodePessimisticDuration(); |
2414 | |
2415 | // Completion |
2416 | case NodeStatus: return ToolTip::nodeStatus(); |
2417 | case NodeCompleted: return ToolTip::nodeCompletion(); |
2418 | case NodePlannedEffort: return ToolTip::nodePlannedEffortTo(); |
2419 | case NodeActualEffort: return ToolTip::nodeActualEffortTo(); |
2420 | case NodeRemainingEffort: return ToolTip::nodeRemainingEffort(); |
2421 | case NodePlannedCost: return ToolTip::nodePlannedCostTo(); |
2422 | case NodeActualCost: return ToolTip::nodeActualCostTo(); |
2423 | case NodeActualStart: return ToolTip::completionStartedTime(); |
2424 | case NodeStarted: return ToolTip::completionStarted(); |
2425 | case NodeActualFinish: return ToolTip::completionFinishedTime(); |
2426 | case NodeFinished: return ToolTip::completionFinished(); |
2427 | case NodeStatusNote: return ToolTip::completionStatusNote(); |
2428 | |
2429 | // Scheduling errors |
2430 | case NodeSchedulingStatus: return ToolTip::nodeSchedulingStatus(); |
2431 | case NodeNotScheduled: return ToolTip::nodeNotScheduled(); |
2432 | case NodeAssignmentMissing: return ToolTip::nodeAssignmentMissing(); |
2433 | case NodeResourceOverbooked: return ToolTip::nodeResourceOverbooked(); |
2434 | case NodeResourceUnavailable: return ToolTip::nodeResourceUnavailable(); |
2435 | case NodeConstraintsError: return ToolTip::nodeConstraintsError(); |
2436 | case NodeEffortNotMet: return ToolTip::nodeEffortNotMet(); |
2437 | case NodeSchedulingError: return ToolTip::nodeSchedulingError(); |
2438 | |
2439 | case NodeWBSCode: return ToolTip::nodeWBS(); |
2440 | case NodeLevel: return ToolTip::nodeLevel(); |
2441 | |
2442 | // Performance |
2443 | case NodeBCWS: return ToolTip::nodeBCWS(); |
2444 | case NodeBCWP: return ToolTip::nodeBCWP(); |
2445 | case NodeACWP: return ToolTip::nodeACWP(); |
2446 | case NodePerformanceIndex: return ToolTip::nodePerformanceIndex(); |
2447 | |
2448 | // Work package handling FIXME |
2449 | case WPOwnerName: return i18nc( "@info:tooltip" , "Work package owner" ); |
2450 | case WPTransmitionStatus: return i18nc( "@info:tooltip" , "Work package status" ); |
2451 | case WPTransmitionTime: return i18nc( "@info:tooltip" , "Work package send/receive time" ); |
2452 | |
2453 | default: return QVariant(); |
2454 | } |
2455 | } |
2456 | if ( role == Qt::TextAlignmentRole ) { |
2457 | switch (section) { |
2458 | case NodeName: |
2459 | case NodeType: |
2460 | case NodeResponsible: |
2461 | case NodeAllocation: |
2462 | case NodeEstimateType: |
2463 | case NodeEstimateCalendar: |
2464 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2465 | case NodeEstimate: |
2466 | case NodeOptimisticRatio: |
2467 | case NodePessimisticRatio: |
2468 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2469 | case NodeRisk: |
2470 | case NodeConstraint: |
2471 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2472 | case NodeConstraintStart: |
2473 | case NodeConstraintEnd: |
2474 | case NodeRunningAccount: |
2475 | case NodeStartupAccount: |
2476 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2477 | case NodeStartupCost: |
2478 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2479 | case NodeShutdownAccount: |
2480 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2481 | case NodeShutdownCost: |
2482 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2483 | case NodeDescription: |
2484 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2485 | |
2486 | // Based on edited values |
2487 | case NodeExpected: |
2488 | case NodeVarianceEstimate: |
2489 | case NodeOptimistic: |
2490 | case NodePessimistic: |
2491 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2492 | |
2493 | // After scheduling |
2494 | case NodeStartTime: |
2495 | case NodeEndTime: |
2496 | case NodeEarlyStart: |
2497 | case NodeEarlyFinish: |
2498 | case NodeLateStart: |
2499 | case NodeLateFinish: |
2500 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2501 | case NodePositiveFloat: |
2502 | case NodeFreeFloat: |
2503 | case NodeNegativeFloat: |
2504 | case NodeStartFloat: |
2505 | case NodeFinishFloat: |
2506 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2507 | case NodeAssignments: |
2508 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2509 | |
2510 | // Based on scheduled values |
2511 | case NodeDuration: |
2512 | case NodeVarianceDuration: |
2513 | case NodeOptimisticDuration: |
2514 | case NodePessimisticDuration: |
2515 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2516 | |
2517 | // Completion |
2518 | case NodeStatus: |
2519 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2520 | case NodeCompleted: |
2521 | return (int)(Qt::AlignCenter); // special, presented as a bar |
2522 | case NodePlannedEffort: |
2523 | case NodeActualEffort: |
2524 | case NodeRemainingEffort: |
2525 | case NodePlannedCost: |
2526 | case NodeActualCost: |
2527 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2528 | case NodeActualStart: |
2529 | case NodeStarted: |
2530 | case NodeActualFinish: |
2531 | case NodeFinished: |
2532 | case NodeStatusNote: |
2533 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2534 | |
2535 | // Scheduling errors |
2536 | case NodeSchedulingStatus: |
2537 | case NodeNotScheduled: |
2538 | case NodeAssignmentMissing: |
2539 | case NodeResourceOverbooked: |
2540 | case NodeResourceUnavailable: |
2541 | case NodeConstraintsError: |
2542 | case NodeEffortNotMet: |
2543 | case NodeSchedulingError: |
2544 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2545 | |
2546 | case NodeWBSCode: |
2547 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2548 | case NodeLevel: |
2549 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2550 | |
2551 | // Performance |
2552 | case NodeBCWS: |
2553 | case NodeBCWP: |
2554 | case NodeACWP: |
2555 | case NodePerformanceIndex: |
2556 | return (int)(Qt::AlignRight|Qt::AlignVCenter); // number |
2557 | case NodeCritical: |
2558 | case NodeCriticalPath: |
2559 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2560 | |
2561 | case WPOwnerName: |
2562 | case WPTransmitionStatus: |
2563 | case WPTransmitionTime: |
2564 | return (int)(Qt::AlignLeft|Qt::AlignVCenter); |
2565 | default: |
2566 | return QVariant(); |
2567 | } |
2568 | } |
2569 | if ( role == Qt::WhatsThisRole ) { |
2570 | switch ( section ) { |
2571 | case NodeNegativeFloat: return WhatsThis::nodeNegativeFloat(); |
2572 | |
2573 | default: return QVariant(); |
2574 | } |
2575 | } |
2576 | return QVariant(); |
2577 | } |
2578 | |
2579 | KUndo2Command *NodeModel::setName( Node *node, const QVariant &value, int role ) |
2580 | { |
2581 | switch ( role ) { |
2582 | case Qt::EditRole: { |
2583 | if ( value.toString() == node->name() ) { |
2584 | return 0; |
2585 | } |
2586 | KUndo2MagicString s = kundo2_i18n( "Modify name" ); |
2587 | switch ( node->type() ) { |
2588 | case Node::Type_Task: s = kundo2_i18n( "Modify task name" ); break; |
2589 | case Node::Type_Milestone: s = kundo2_i18n( "Modify milestone name" ); break; |
2590 | case Node::Type_Summarytask: s = kundo2_i18n( "Modify summarytask name" ); break; |
2591 | case Node::Type_Project: s = kundo2_i18n( "Modify project name" ); break; |
2592 | } |
2593 | return new NodeModifyNameCmd( *node, value.toString(), s ); |
2594 | } |
2595 | } |
2596 | return 0; |
2597 | } |
2598 | |
2599 | KUndo2Command *NodeModel::setLeader( Node *node, const QVariant &value, int role ) |
2600 | { |
2601 | switch ( role ) { |
2602 | case Qt::EditRole: { |
2603 | if ( value.toString() != node->leader() ) { |
2604 | return new NodeModifyLeaderCmd( *node, value.toString(), kundo2_i18n( "Modify responsible" ) ); |
2605 | } |
2606 | break; |
2607 | } |
2608 | default: |
2609 | break; |
2610 | } |
2611 | return 0; |
2612 | } |
2613 | |
2614 | KUndo2Command *NodeModel::setAllocation( Node */*node*/, const QVariant &/*value*/, int /*role*/ ) |
2615 | { |
2616 | return 0; |
2617 | } |
2618 | |
2619 | KUndo2Command *NodeModel::setDescription( Node *node, const QVariant &value, int role ) |
2620 | { |
2621 | switch ( role ) { |
2622 | case Qt::EditRole: |
2623 | if ( value.toString() == node->description() ) { |
2624 | return 0; |
2625 | } |
2626 | return new NodeModifyDescriptionCmd( *node, value.toString(), kundo2_i18n( "Modify task description" ) ); |
2627 | } |
2628 | return 0; |
2629 | } |
2630 | |
2631 | KUndo2Command *NodeModel::setType( Node *, const QVariant &, int ) |
2632 | { |
2633 | return 0; |
2634 | } |
2635 | |
2636 | KUndo2Command *NodeModel::setConstraint( Node *node, const QVariant &value, int role ) |
2637 | { |
2638 | switch ( role ) { |
2639 | case Qt::EditRole: { |
2640 | Node::ConstraintType v; |
2641 | QStringList lst = node->constraintList( false ); |
2642 | if ( lst.contains( value.toString() ) ) { |
2643 | v = Node::ConstraintType( lst.indexOf( value.toString() ) ); |
2644 | } else { |
2645 | v = Node::ConstraintType( value.toInt() ); |
2646 | } |
2647 | //kDebug(planDbg())<<v; |
2648 | if ( v != node->constraint() ) { |
2649 | return new NodeModifyConstraintCmd( *node, v, kundo2_i18n( "Modify constraint type" ) ); |
2650 | } |
2651 | break; |
2652 | } |
2653 | default: |
2654 | break; |
2655 | } |
2656 | return 0; |
2657 | } |
2658 | |
2659 | KUndo2Command *NodeModel::setConstraintStartTime( Node *node, const QVariant &value, int role ) |
2660 | { |
2661 | switch ( role ) { |
2662 | case Qt::EditRole: { |
2663 | QDateTime dt = value.toDateTime(); |
2664 | dt.setTime( QTime( dt.time().hour(), dt.time().minute() ) ); // reset possible secs/msecs |
2665 | if ( dt != node->constraintStartTime() ) { |
2666 | return new NodeModifyConstraintStartTimeCmd( *node, dt, kundo2_i18n( "Modify constraint start time" ) ); |
2667 | } |
2668 | break; |
2669 | } |
2670 | default: |
2671 | break; |
2672 | } |
2673 | return 0; |
2674 | } |
2675 | |
2676 | KUndo2Command *NodeModel::setConstraintEndTime( Node *node, const QVariant &value, int role ) |
2677 | { |
2678 | switch ( role ) { |
2679 | case Qt::EditRole: { |
2680 | QDateTime dt = value.toDateTime(); |
2681 | dt.setTime( QTime( dt.time().hour(), dt.time().minute() ) ); // reset possible secs/msecs |
2682 | if ( dt != node->constraintEndTime() ) { |
2683 | return new NodeModifyConstraintEndTimeCmd( *node, dt, kundo2_i18n( "Modify constraint end time" ) ); |
2684 | } |
2685 | break; |
2686 | } |
2687 | default: |
2688 | break; |
2689 | } |
2690 | return 0; |
2691 | } |
2692 | |
2693 | KUndo2Command *NodeModel::setEstimateType( Node *node, const QVariant &value, int role ) |
2694 | { |
2695 | if ( node->estimate() == 0 ) { |
2696 | return 0; |
2697 | } |
2698 | switch ( role ) { |
2699 | case Qt::EditRole: { |
2700 | Estimate::Type v; |
2701 | QStringList lst = node->estimate()->typeToStringList( false ); |
2702 | if ( lst.contains( value.toString() ) ) { |
2703 | v = Estimate::Type( lst.indexOf( value.toString() ) ); |
2704 | } else { |
2705 | v = Estimate::Type( value.toInt() ); |
2706 | } |
2707 | if ( v != node->estimate()->type() ) { |
2708 | return new ModifyEstimateTypeCmd( *node, node->estimate()->type(), v, kundo2_i18n( "Modify estimate type" ) ); |
2709 | } |
2710 | break; |
2711 | } |
2712 | default: |
2713 | break; |
2714 | } |
2715 | return 0; |
2716 | } |
2717 | |
2718 | KUndo2Command *NodeModel::setEstimateCalendar( Node *node, const QVariant &value, int role ) |
2719 | { |
2720 | if ( node->estimate() == 0 ) { |
2721 | return 0; |
2722 | } |
2723 | switch ( role ) { |
2724 | case Qt::EditRole: { |
2725 | Calendar *c = 0; |
2726 | Calendar *old = node->estimate()->calendar(); |
2727 | if ( value.toInt() > 0 ) { |
2728 | QStringList lst = estimateCalendar( node, Role::EnumList ).toStringList(); |
2729 | if ( value.toInt() < lst.count() ) { |
2730 | c = m_project->calendarByName( lst.at( value.toInt() ) ); |
2731 | } |
2732 | } |
2733 | if ( c != old ) { |
2734 | return new ModifyEstimateCalendarCmd( *node, old, c, kundo2_i18n( "Modify estimate calendar" ) ); |
2735 | } |
2736 | break; |
2737 | } |
2738 | default: |
2739 | break; |
2740 | } |
2741 | return 0; |
2742 | } |
2743 | |
2744 | KUndo2Command *NodeModel::setEstimate( Node *node, const QVariant &value, int role ) |
2745 | { |
2746 | if ( node->estimate() == 0 ) { |
2747 | return 0; |
2748 | } |
2749 | switch ( role ) { |
2750 | case Qt::EditRole: { |
2751 | double d; |
2752 | Duration::Unit unit; |
2753 | if ( value.toList().count() == 2 ) { |
2754 | d = value.toList()[0].toDouble(); |
2755 | unit = static_cast<Duration::Unit>( value.toList()[1].toInt() ); |
2756 | } else if ( value.canConvert<QString>() ) { |
2757 | bool ok = Duration::valueFromString( value.toString(), d, unit ); |
2758 | if ( ! ok ) { |
2759 | return 0; |
2760 | } |
2761 | } else { |
2762 | return 0; |
2763 | } |
2764 | //kDebug(planDbg())<<d<<","<<unit<<" ->"<<value.toList()[1].toInt(); |
2765 | MacroCommand *cmd = 0; |
2766 | if ( d != node->estimate()->expectedEstimate() ) { |
2767 | if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Modify estimate" ) ); |
2768 | cmd->addCommand( new ModifyEstimateCmd( *node, node->estimate()->expectedEstimate(), d ) ); |
2769 | } |
2770 | if ( unit != node->estimate()->unit() ) { |
2771 | if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Modify estimate" ) ); |
2772 | cmd->addCommand( new ModifyEstimateUnitCmd( *node, node->estimate()->unit(), unit ) ); |
2773 | } |
2774 | if ( cmd ) { |
2775 | return cmd; |
2776 | } |
2777 | break; |
2778 | } |
2779 | default: |
2780 | break; |
2781 | } |
2782 | return 0; |
2783 | } |
2784 | |
2785 | KUndo2Command *NodeModel::setOptimisticRatio( Node *node, const QVariant &value, int role ) |
2786 | { |
2787 | if ( node->estimate() == 0 ) { |
2788 | return 0; |
2789 | } |
2790 | switch ( role ) { |
2791 | case Qt::EditRole: |
2792 | if ( value.toInt() != node->estimate()->optimisticRatio() ) { |
2793 | return new EstimateModifyOptimisticRatioCmd( *node, node->estimate()->optimisticRatio(), value.toInt(), kundo2_i18n( "Modify optimistic estimate" ) ); |
2794 | } |
2795 | break; |
2796 | default: |
2797 | break; |
2798 | } |
2799 | return 0; |
2800 | } |
2801 | |
2802 | KUndo2Command *NodeModel::setPessimisticRatio( Node *node, const QVariant &value, int role ) |
2803 | { |
2804 | if ( node->estimate() == 0 ) { |
2805 | return 0; |
2806 | } |
2807 | switch ( role ) { |
2808 | case Qt::EditRole: |
2809 | if ( value.toInt() != node->estimate()->pessimisticRatio() ) { |
2810 | return new EstimateModifyPessimisticRatioCmd( *node, node->estimate()->pessimisticRatio(), value.toInt(), kundo2_i18n( "Modify pessimistic estimate" ) ); |
2811 | } |
2812 | default: |
2813 | break; |
2814 | } |
2815 | return 0; |
2816 | } |
2817 | |
2818 | KUndo2Command *NodeModel::setRiskType( Node *node, const QVariant &value, int role ) |
2819 | { |
2820 | if ( node->estimate() == 0 ) { |
2821 | return 0; |
2822 | } |
2823 | switch ( role ) { |
2824 | case Qt::EditRole: { |
2825 | int val = 0; |
2826 | QStringList lst = node->estimate()->risktypeToStringList( false ); |
2827 | if ( lst.contains( value.toString() ) ) { |
2828 | val = lst.indexOf( value.toString() ); |
2829 | } else { |
2830 | val = value.toInt(); |
2831 | } |
2832 | if ( val != node->estimate()->risktype() ) { |
2833 | Estimate::Risktype v = Estimate::Risktype( val ); |
2834 | return new EstimateModifyRiskCmd( *node, node->estimate()->risktype(), v, kundo2_i18n( "Modify risk type" ) ); |
2835 | } |
2836 | break; |
2837 | } |
2838 | default: |
2839 | break; |
2840 | } |
2841 | return 0; |
2842 | } |
2843 | |
2844 | KUndo2Command *NodeModel::setRunningAccount( Node *node, const QVariant &value, int role ) |
2845 | { |
2846 | switch ( role ) { |
2847 | case Qt::EditRole: { |
2848 | //kDebug(planDbg())<<node->name(); |
2849 | QStringList lst = runningAccount( node, Role::EnumList ).toStringList(); |
2850 | if ( value.toInt() < lst.count() ) { |
2851 | Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); |
2852 | Account *old = node->runningAccount(); |
2853 | if ( old != a ) { |
2854 | return new NodeModifyRunningAccountCmd( *node, old, a, kundo2_i18n( "Modify running account" ) ); |
2855 | } |
2856 | } |
2857 | break; |
2858 | } |
2859 | default: |
2860 | break; |
2861 | } |
2862 | return 0; |
2863 | } |
2864 | |
2865 | KUndo2Command *NodeModel::setStartupAccount( Node *node, const QVariant &value, int role ) |
2866 | { |
2867 | switch ( role ) { |
2868 | case Qt::EditRole: { |
2869 | //kDebug(planDbg())<<node->name(); |
2870 | QStringList lst = startupAccount( node, Role::EnumList ).toStringList(); |
2871 | if ( value.toInt() < lst.count() ) { |
2872 | Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); |
2873 | Account *old = node->startupAccount(); |
2874 | //kDebug(planDbg())<<(value.toInt())<<";"<<(lst.at( value.toInt()))<<":"<<a; |
2875 | if ( old != a ) { |
2876 | return new NodeModifyStartupAccountCmd( *node, old, a, kundo2_i18n( "Modify startup account" ) ); |
2877 | } |
2878 | } |
2879 | break; |
2880 | } |
2881 | default: |
2882 | break; |
2883 | } |
2884 | return 0; |
2885 | } |
2886 | |
2887 | KUndo2Command *NodeModel::setStartupCost( Node *node, const QVariant &value, int role ) |
2888 | { |
2889 | switch ( role ) { |
2890 | case Qt::EditRole: { |
2891 | double v = KGlobal::locale()->readMoney( value.toString() ); |
2892 | if ( v != node->startupCost() ) { |
2893 | return new NodeModifyStartupCostCmd( *node, v, kundo2_i18n( "Modify startup cost" ) ); |
2894 | } |
2895 | break; |
2896 | } |
2897 | default: |
2898 | break; |
2899 | } |
2900 | return 0; |
2901 | } |
2902 | |
2903 | KUndo2Command *NodeModel::setShutdownAccount( Node *node, const QVariant &value, int role ) |
2904 | { |
2905 | switch ( role ) { |
2906 | case Qt::EditRole: { |
2907 | //kDebug(planDbg())<<node->name(); |
2908 | QStringList lst = shutdownAccount( node, Role::EnumList ).toStringList(); |
2909 | if ( value.toInt() < lst.count() ) { |
2910 | Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); |
2911 | Account *old = node->shutdownAccount(); |
2912 | if ( old != a ) { |
2913 | return new NodeModifyShutdownAccountCmd( *node, old, a, kundo2_i18n( "Modify shutdown account" ) ); |
2914 | } |
2915 | } |
2916 | break; |
2917 | } |
2918 | default: |
2919 | break; |
2920 | } |
2921 | return 0; |
2922 | } |
2923 | |
2924 | KUndo2Command *NodeModel::setShutdownCost( Node *node, const QVariant &value, int role ) |
2925 | { |
2926 | switch ( role ) { |
2927 | case Qt::EditRole: { |
2928 | double v = KGlobal::locale()->readMoney( value.toString() ); |
2929 | if ( v != node->shutdownCost() ) { |
2930 | return new NodeModifyShutdownCostCmd( *node, v, kundo2_i18n( "Modify shutdown cost" ) ); |
2931 | } |
2932 | break; |
2933 | } |
2934 | default: |
2935 | break; |
2936 | } |
2937 | return 0; |
2938 | } |
2939 | |
2940 | KUndo2Command *NodeModel::setCompletion( Node */*node*/, const QVariant &/*value*/, int /*role*/ ) |
2941 | { |
2942 | return 0; |
2943 | } |
2944 | |
2945 | KUndo2Command *NodeModel::setRemainingEffort( Node *node, const QVariant &value, int role ) |
2946 | { |
2947 | if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { |
2948 | Task *t = static_cast<Task*>( node ); |
2949 | double d( value.toList()[0].toDouble() ); |
2950 | Duration::Unit unit = static_cast<Duration::Unit>( value.toList()[1].toInt() ); |
2951 | Duration dur( d, unit ); |
2952 | return new ModifyCompletionRemainingEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify remaining effort" ) ); |
2953 | } |
2954 | return 0; |
2955 | } |
2956 | |
2957 | KUndo2Command *NodeModel::setActualEffort( Node *node, const QVariant &value, int role ) |
2958 | { |
2959 | if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { |
2960 | Task *t = static_cast<Task*>( node ); |
2961 | double d( value.toList()[0].toDouble() ); |
2962 | Duration::Unit unit = static_cast<Duration::Unit>( value.toList()[1].toInt() ); |
2963 | Duration dur( d, unit ); |
2964 | return new ModifyCompletionActualEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify actual effort" ) ); |
2965 | } |
2966 | return 0; |
2967 | } |
2968 | |
2969 | KUndo2Command *NodeModel::setStartedTime( Node *node, const QVariant &value, int role ) |
2970 | { |
2971 | switch ( role ) { |
2972 | case Qt::EditRole: { |
2973 | Task *t = qobject_cast<Task*>( node ); |
2974 | if ( t == 0 ) { |
2975 | return 0; |
2976 | } |
2977 | MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual start time" ) ); |
2978 | if ( ! t->completion().isStarted() ) { |
2979 | m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); |
2980 | } |
2981 | m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); |
2982 | if ( t->type() == Node::Type_Milestone ) { |
2983 | m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); |
2984 | m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); |
2985 | if ( t->completion().percentFinished() < 100 ) { |
2986 | Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); |
2987 | m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); |
2988 | } |
2989 | } |
2990 | return m; |
2991 | } |
2992 | default: |
2993 | break; |
2994 | } |
2995 | return 0; |
2996 | } |
2997 | |
2998 | KUndo2Command *NodeModel::setFinishedTime( Node *node, const QVariant &value, int role ) |
2999 | { |
3000 | switch ( role ) { |
3001 | case Qt::EditRole: { |
3002 | Task *t = qobject_cast<Task*>( node ); |
3003 | if ( t == 0 ) { |
3004 | return 0; |
3005 | } |
3006 | MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual finish time" ) ); |
3007 | if ( ! t->completion().isFinished() ) { |
3008 | m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); |
3009 | if ( t->completion().percentFinished() < 100 ) { |
3010 | Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); |
3011 | m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); |
3012 | } |
3013 | } |
3014 | m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); |
3015 | if ( t->type() == Node::Type_Milestone ) { |
3016 | m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); |
3017 | m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); |
3018 | } |
3019 | return m; |
3020 | } |
3021 | default: |
3022 | break; |
3023 | } |
3024 | return 0; |
3025 | } |
3026 | |
3027 | //---------------------------- |
3028 | NodeItemModel::NodeItemModel( QObject *parent ) |
3029 | : ItemModelBase( parent ), |
3030 | m_node( 0 ), |
3031 | m_projectshown( false ) |
3032 | { |
3033 | setReadOnly( NodeModel::NodeDescription, true ); |
3034 | } |
3035 | |
3036 | NodeItemModel::~NodeItemModel() |
3037 | { |
3038 | } |
3039 | |
3040 | void NodeItemModel::setShowProject( bool on ) |
3041 | { |
3042 | m_projectshown = on; |
3043 | reset(); |
3044 | emit projectShownChanged( on ); |
3045 | } |
3046 | |
3047 | void NodeItemModel::slotNodeToBeInserted( Node *parent, int row ) |
3048 | { |
3049 | //kDebug(planDbg())<<parent->name()<<"; "<<row; |
3050 | Q_ASSERT( m_node == 0 ); |
3051 | m_node = parent; |
3052 | beginInsertRows( index( parent ), row, row ); |
3053 | } |
3054 | |
3055 | void NodeItemModel::slotNodeInserted( Node *node ) |
3056 | { |
3057 | //kDebug(planDbg())<<node->parentNode()->name()<<"-->"<<node->name(); |
3058 | Q_ASSERT( node->parentNode() == m_node ); |
3059 | endInsertRows(); |
3060 | m_node = 0; |
3061 | emit nodeInserted( node ); |
3062 | } |
3063 | |
3064 | void NodeItemModel::slotNodeToBeRemoved( Node *node ) |
3065 | { |
3066 | //kDebug(planDbg())<<node->name(); |
3067 | Q_ASSERT( m_node == 0 ); |
3068 | m_node = node; |
3069 | int row = index( node ).row(); |
3070 | beginRemoveRows( index( node->parentNode() ), row, row ); |
3071 | } |
3072 | |
3073 | void NodeItemModel::slotNodeRemoved( Node *node ) |
3074 | { |
3075 | //kDebug(planDbg())<<node->name(); |
3076 | Q_ASSERT( node == m_node ); |
3077 | #ifdef NDEBUG |
3078 | Q_UNUSED(node) |
3079 | #endif |
3080 | endRemoveRows(); |
3081 | m_node = 0; |
3082 | } |
3083 | |
3084 | void NodeItemModel::slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ) |
3085 | { |
3086 | //kDebug(planDbg())<<node->parentNode()->name()<<pos<<":"<<newParent->name()<<newPos; |
3087 | beginMoveRows( index( node->parentNode() ), pos, pos, index( newParent ), newPos ); |
3088 | } |
3089 | |
3090 | void NodeItemModel::slotNodeMoved( Node *node ) |
3091 | { |
3092 | Q_UNUSED( node ); |
3093 | //kDebug(planDbg())<<node->parentNode()->name()<<node->parentNode()->indexOf( node ); |
3094 | endMoveRows(); |
3095 | } |
3096 | |
3097 | void NodeItemModel::slotLayoutChanged() |
3098 | { |
3099 | //kDebug(planDbg())<<node->name(); |
3100 | emit layoutAboutToBeChanged(); |
3101 | emit layoutChanged(); |
3102 | } |
3103 | |
3104 | void NodeItemModel::slotProjectCalulated(ScheduleManager *sm) |
3105 | { |
3106 | kDebug(planDbg())<<m_manager<<sm; |
3107 | if ( sm && sm == m_manager ) { |
3108 | slotLayoutChanged(); |
3109 | } |
3110 | } |
3111 | |
3112 | void NodeItemModel::slotWbsDefinitionChanged() |
3113 | { |
3114 | kDebug(planDbg()); |
3115 | if ( m_project == 0 ) { |
3116 | return; |
3117 | } |
3118 | if ( m_projectshown ) { |
3119 | QModelIndex idx = createIndex( 0, NodeModel::NodeWBSCode, m_project ); |
3120 | emit dataChanged( idx, idx ); |
3121 | } |
3122 | foreach ( Node *n, m_project->allNodes() ) { |
3123 | int row = n->parentNode()->indexOf( n ); |
3124 | QModelIndex idx = createIndex( row, NodeModel::NodeWBSCode, n ); |
3125 | emit dataChanged( idx, idx ); |
3126 | } |
3127 | } |
3128 | |
3129 | |
3130 | void NodeItemModel::setProject( Project *project ) |
3131 | { |
3132 | if ( m_project ) { |
3133 | disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); |
3134 | disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); |
3135 | disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); |
3136 | disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); |
3137 | disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); |
3138 | |
3139 | disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int)) ); |
3140 | disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); |
3141 | |
3142 | disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); |
3143 | disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); |
3144 | disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalulated(ScheduleManager*))); |
3145 | } |
3146 | m_project = project; |
3147 | kDebug(planDbg())<<this<<m_project<<"->" <<project; |
3148 | m_nodemodel.setProject( project ); |
3149 | if ( project ) { |
3150 | connect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); |
3151 | connect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); |
3152 | connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); |
3153 | connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); |
3154 | connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); |
3155 | |
3156 | connect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int)) ); |
3157 | connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); |
3158 | |
3159 | connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); |
3160 | connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); |
3161 | connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalulated(ScheduleManager*))); |
3162 | } |
3163 | reset(); |
3164 | } |
3165 | |
3166 | void NodeItemModel::setScheduleManager( ScheduleManager *sm ) |
3167 | { |
3168 | if ( m_nodemodel.manager() ) { |
3169 | } |
3170 | m_nodemodel.setManager( sm ); |
3171 | ItemModelBase::setScheduleManager( sm ); |
3172 | if ( sm ) { |
3173 | } |
3174 | kDebug(planDbg())<<this<<sm; |
3175 | reset(); |
3176 | } |
3177 | |
3178 | Qt::ItemFlags NodeItemModel::flags( const QModelIndex &index ) const |
3179 | { |
3180 | Qt::ItemFlags flags = QAbstractItemModel::flags( index ); |
3181 | if ( !index.isValid() ) { |
3182 | if ( m_readWrite ) { |
3183 | flags |= Qt::ItemIsDropEnabled; |
3184 | } |
3185 | return flags; |
3186 | } |
3187 | if ( isColumnReadOnly( index.column() ) ) { |
3188 | //kDebug(planDbg())<<"Column is readonly:"<<index.column(); |
3189 | return flags; |
3190 | } |
3191 | Node *n = node( index ); |
3192 | if ( m_readWrite && n != 0 ) { |
3193 | bool baselined = n->isBaselined(); |
3194 | flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; |
3195 | switch ( index.column() ) { |
3196 | case NodeModel::NodeName: // name |
3197 | flags |= Qt::ItemIsEditable; |
3198 | break; |
3199 | case NodeModel::NodeType: break; // Node type |
3200 | case NodeModel::NodeResponsible: // Responsible |
3201 | flags |= Qt::ItemIsEditable; |
3202 | break; |
3203 | case NodeModel::NodeAllocation: // allocation |
3204 | if ( n->type() == Node::Type_Task ) { |
3205 | flags |= Qt::ItemIsEditable; |
3206 | } |
3207 | break; |
3208 | case NodeModel::NodeEstimateType: // estimateType |
3209 | { |
3210 | if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3211 | flags |= Qt::ItemIsEditable; |
3212 | } |
3213 | break; |
3214 | } |
3215 | case NodeModel::NodeEstimate: // estimate |
3216 | { |
3217 | if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3218 | flags |= Qt::ItemIsEditable; |
3219 | } |
3220 | break; |
3221 | } |
3222 | case NodeModel::NodeOptimisticRatio: // optimisticRatio |
3223 | case NodeModel::NodePessimisticRatio: // pessimisticRatio |
3224 | { |
3225 | if ( ! baselined && n->type() == Node::Type_Task ) { |
3226 | flags |= Qt::ItemIsEditable; |
3227 | } |
3228 | break; |
3229 | } |
3230 | case NodeModel::NodeEstimateCalendar: |
3231 | { |
3232 | if ( ! baselined && n->type() == Node::Type_Task ) |
3233 | { |
3234 | flags |= Qt::ItemIsEditable; |
3235 | } |
3236 | break; |
3237 | } |
3238 | case NodeModel::NodeRisk: // risktype |
3239 | { |
3240 | if ( ! baselined && n->type() == Node::Type_Task ) { |
3241 | flags |= Qt::ItemIsEditable; |
3242 | } |
3243 | break; |
3244 | } |
3245 | case NodeModel::NodeConstraint: // constraint type |
3246 | if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3247 | flags |= Qt::ItemIsEditable; |
3248 | } |
3249 | break; |
3250 | case NodeModel::NodeConstraintStart: { // constraint start |
3251 | if ( ! baselined && n->type() == Node::Type_Project ) { |
3252 | flags |= Qt::ItemIsEditable; |
3253 | break; |
3254 | } |
3255 | if ( ! baselined && ! ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3256 | break; |
3257 | } |
3258 | flags |= Qt::ItemIsEditable; |
3259 | break; |
3260 | } |
3261 | case NodeModel::NodeConstraintEnd: { // constraint end |
3262 | if ( ! baselined && n->type() == Node::Type_Project ) { |
3263 | flags |= Qt::ItemIsEditable; |
3264 | break; |
3265 | } |
3266 | if ( ! baselined && ! ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3267 | break; |
3268 | } |
3269 | flags |= Qt::ItemIsEditable; |
3270 | break; |
3271 | } |
3272 | case NodeModel::NodeRunningAccount: // running account |
3273 | if ( ! baselined && n->type() == Node::Type_Task ) { |
3274 | flags |= Qt::ItemIsEditable; |
3275 | } |
3276 | break; |
3277 | case NodeModel::NodeStartupAccount: // startup account |
3278 | case NodeModel::NodeStartupCost: // startup cost |
3279 | case NodeModel::NodeShutdownAccount: // shutdown account |
3280 | case NodeModel::NodeShutdownCost: { // shutdown cost |
3281 | if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { |
3282 | flags |= Qt::ItemIsEditable; |
3283 | } |
3284 | break; |
3285 | } |
3286 | case NodeModel::NodeDescription: // description |
3287 | flags |= Qt::ItemIsEditable; |
3288 | break; |
3289 | default: |
3290 | break; |
3291 | } |
3292 | Task *t = static_cast<Task*>( n ); |
3293 | if ( manager() && t->isScheduled( id() ) ) { |
3294 | if ( ! t->completion().isStarted() ) { |
3295 | switch ( index.column() ) { |
3296 | case NodeModel::NodeActualStart: |
3297 | flags |= Qt::ItemIsEditable; |
3298 | break; |
3299 | case NodeModel::NodeActualFinish: |
3300 | if ( t->type() == Node::Type_Milestone ) { |
3301 | flags |= Qt::ItemIsEditable; |
3302 | } |
3303 | break; |
3304 | case NodeModel::NodeCompleted: |
3305 | if ( t->state() & Node::State_ReadyToStart ) { |
3306 | flags |= Qt::ItemIsEditable; |
3307 | } |
3308 | break; |
3309 | |
3310 | default: break; |
3311 | } |
3312 | } else if ( ! t->completion().isFinished() ) { |
3313 | switch ( index.column() ) { |
3314 | case NodeModel::NodeActualFinish: |
3315 | case NodeModel::NodeCompleted: |
3316 | case NodeModel::NodeRemainingEffort: |
3317 | flags |= Qt::ItemIsEditable; |
3318 | break; |
3319 | case NodeModel::NodeActualEffort: |
3320 | if ( t->completion().entrymode() == Completion::EnterEffortPerTask || t->completion().entrymode() == Completion::EnterEffortPerResource ) { |
3321 | flags |= Qt::ItemIsEditable; |
3322 | } |
3323 | break; |
3324 | default: break; |
3325 | } |
3326 | } |
3327 | } |
3328 | } |
3329 | return flags; |
3330 | } |
3331 | |
3332 | |
3333 | QModelIndex NodeItemModel::parent( const QModelIndex &index ) const |
3334 | { |
3335 | if ( ! index.isValid() ) { |
3336 | return QModelIndex(); |
3337 | } |
3338 | Node *n = node( index ); |
3339 | if ( n == 0 || n == m_project ) { |
3340 | return QModelIndex(); |
3341 | } |
3342 | Node *p = n->parentNode(); |
3343 | if ( p == m_project ) { |
3344 | return m_projectshown ? createIndex( 0, 0, p ) : QModelIndex(); |
3345 | } |
3346 | int row = p->parentNode()->indexOf( p ); |
3347 | if ( row == -1 ) { |
3348 | return QModelIndex(); |
3349 | } |
3350 | return createIndex( row, 0, p ); |
3351 | } |
3352 | |
3353 | QModelIndex NodeItemModel::index( int row, int column, const QModelIndex &parent ) const |
3354 | { |
3355 | if ( parent.isValid() ) { |
3356 | Q_ASSERT( parent.model() == this ); |
3357 | } |
3358 | //kDebug(planDbg())<<parent<<row<<column; |
3359 | if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) { |
3360 | //kDebug(planDbg())<<m_project<<parent<<"No index for"<<row<<","<<column; |
3361 | return QModelIndex(); |
3362 | } |
3363 | if ( m_projectshown && ! parent.isValid() ) { |
3364 | return createIndex( row, column, m_project ); |
3365 | } |
3366 | Node *p = node( parent ); |
3367 | if ( row >= p->numChildren() ) { |
3368 | kError()<<p->name()<<" row too high" <<row<<"," <<column; |
3369 | return QModelIndex(); |
3370 | } |
3371 | // now get the internal pointer for the index |
3372 | Node *n = p->childNode( row ); |
3373 | QModelIndex idx = createIndex(row, column, n); |
3374 | //kDebug(planDbg())<<idx; |
3375 | return idx; |
3376 | } |
3377 | |
3378 | QModelIndex NodeItemModel::index( const Node *node, int column ) const |
3379 | { |
3380 | if ( m_project == 0 || node == 0 ) { |
3381 | return QModelIndex(); |
3382 | } |
3383 | Node *par = node->parentNode(); |
3384 | if ( par ) { |
3385 | //kDebug(planDbg())<<par<<"-->"<<node; |
3386 | return createIndex( par->indexOf( node ), column, const_cast<Node*>(node) ); |
3387 | } |
3388 | if ( m_projectshown && node == m_project ) { |
3389 | return createIndex( 0, column, m_project ); |
3390 | } |
3391 | //kDebug(planDbg())<<node; |
3392 | return QModelIndex(); |
3393 | } |
3394 | |
3395 | bool NodeItemModel::setType( Node *, const QVariant &, int ) |
3396 | { |
3397 | return false; |
3398 | } |
3399 | |
3400 | bool NodeItemModel::setAllocation( Node *node, const QVariant &value, int role ) |
3401 | { |
3402 | Task *task = qobject_cast<Task*>( node ); |
3403 | if ( task == 0 ) { |
3404 | return false; |
3405 | } |
3406 | switch ( role ) { |
3407 | case Qt::EditRole: |
3408 | { |
3409 | MacroCommand *cmd = 0; |
3410 | QStringList res = m_project->resourceNameList(); |
3411 | QStringList req = node->requestNameList(); |
3412 | QStringList alloc; |
3413 | foreach ( const QString &s, value.toString().split( QRegExp(" *, *" ), QString::SkipEmptyParts ) ) { |
3414 | alloc << s.trimmed(); |
3415 | } |
3416 | // first add all new resources (to "default" group) |
3417 | ResourceGroup *pargr = m_project->groupByName( i18n( "Resources" ) ); |
3418 | foreach ( const QString &s, alloc ) { |
3419 | Resource *r = m_project->resourceByName( s.trimmed() ); |
3420 | if ( r != 0 ) { |
3421 | continue; |
3422 | } |
3423 | if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Add resource" ) ); |
3424 | if ( pargr == 0 ) { |
3425 | pargr = new ResourceGroup(); |
3426 | pargr->setName( i18n( "Resources" ) ); |
3427 | cmd->addCommand( new AddResourceGroupCmd( m_project, pargr ) ); |
3428 | //kDebug(planDbg())<<"add group:"<<pargr->name(); |
3429 | } |
3430 | r = new Resource(); |
3431 | r->setName( s.trimmed() ); |
3432 | cmd->addCommand( new AddResourceCmd( pargr, r ) ); |
3433 | //kDebug(planDbg())<<"add resource:"<<r->name(); |
3434 | emit executeCommand( cmd ); |
3435 | cmd = 0; |
3436 | } |
3437 | |
3438 | KUndo2MagicString c = kundo2_i18n( "Modify resource allocations" ); |
3439 | // Handle deleted requests |
3440 | foreach ( const QString &s, req ) { |
3441 | // if a request is not in alloc, it must have been be removed by the user |
3442 | if ( alloc.indexOf( s ) == -1 ) { |
3443 | // remove removed resource request |
3444 | ResourceRequest *r = node->resourceRequest( s ); |
3445 | if ( r ) { |
3446 | if ( cmd == 0 ) cmd = new MacroCommand( c ); |
3447 | //kDebug(planDbg())<<"delete request:"<<r->resource()->name()<<" group:"<<r->parent()->group()->name(); |
3448 | cmd->addCommand( new RemoveResourceRequestCmd( r->parent(), r ) ); |
3449 | } |
3450 | } |
3451 | } |
3452 | // Handle new requests |
3453 | QMap<ResourceGroup*, ResourceGroupRequest*> groupmap; |
3454 | foreach ( const QString &s, alloc ) { |
3455 | // if an allocation is not in req, it must be added |
3456 | if ( req.indexOf( s ) == -1 ) { |
3457 | ResourceGroup *pargr = 0; |
3458 | Resource *r = m_project->resourceByName( s ); |
3459 | if ( r == 0 ) { |
3460 | // Handle request to non exixting resource |
3461 | pargr = m_project->groupByName( i18n( "Resources" ) ); |
3462 | if ( pargr == 0 ) { |
3463 | pargr = new ResourceGroup(); |
3464 | pargr->setName( i18n( "Resources" ) ); |
3465 | cmd->addCommand( new AddResourceGroupCmd( m_project, pargr ) ); |
3466 | //kDebug(planDbg())<<"add group:"<<pargr->name(); |
3467 | } |
3468 | r = new Resource(); |
3469 | r->setName( s ); |
3470 | cmd->addCommand( new AddResourceCmd( pargr, r ) ); |
3471 | //kDebug(planDbg())<<"add resource:"<<r->name(); |
3472 | emit executeCommand( cmd ); |
3473 | cmd = 0; |
3474 | } else { |
3475 | pargr = r->parentGroup(); |
3476 | //kDebug(planDbg())<<"add '"<<r->name()<<"' to group:"<<pargr; |
3477 | } |
3478 | // add request |
3479 | ResourceGroupRequest *g = node->resourceGroupRequest( pargr ); |
3480 | if ( g == 0 ) { |
3481 | g = groupmap.value( pargr ); |
3482 | } |
3483 | if ( g == 0 ) { |
3484 | // create a group request |
3485 | if ( cmd == 0 ) cmd = new MacroCommand( c ); |
3486 | g = new ResourceGroupRequest( pargr ); |
3487 | cmd->addCommand( new AddResourceGroupRequestCmd( *task, g ) ); |
3488 | groupmap.insert( pargr, g ); |
3489 | //kDebug(planDbg())<<"add group request:"<<g; |
3490 | } |
3491 | if ( cmd == 0 ) cmd = new MacroCommand( c ); |
3492 | cmd->addCommand( new AddResourceRequestCmd( g, new ResourceRequest( r, r->units() ) ) ); |
3493 | //kDebug(planDbg())<<"add request:"<<r->name()<<" group:"<<g; |
3494 | } |
3495 | } |
3496 | if ( cmd ) { |
3497 | emit executeCommand( cmd ); |
3498 | return true; |
3499 | } |
3500 | } |
3501 | } |
3502 | return false; |
3503 | } |
3504 | |
3505 | bool NodeItemModel::setCompletion( Node *node, const QVariant &value, int role ) |
3506 | { |
3507 | kDebug(planDbg())<<node->name()<<value<<role; |
3508 | if ( role != Qt::EditRole ) { |
3509 | return 0; |
3510 | } |
3511 | if ( node->type() == Node::Type_Task ) { |
3512 | Completion &c = static_cast<Task*>( node )->completion(); |
3513 | QDateTime dt = QDateTime::currentDateTime(); |
3514 | QDate date = dt.date(); |
3515 | MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify completion" ) ); |
3516 | if ( ! c.isStarted() ) { |
3517 | m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); |
3518 | m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); |
3519 | } |
3520 | m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, value.toInt() ) ); |
3521 | if ( value.toInt() == 100 ) { |
3522 | m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); |
3523 | m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); |
3524 | } |
3525 | emit executeCommand( m ); // also adds a new entry if necessary |
3526 | if ( c.entrymode() == Completion::EnterCompleted ) { |
3527 | Duration planned = static_cast<Task*>( node )->plannedEffort( m_nodemodel.id() ); |
3528 | Duration actual = ( planned * value.toInt() ) / 100; |
3529 | kDebug(planDbg())<<planned.toString()<<value.toInt()<<actual.toString(); |
3530 | NamedCommand *cmd = new ModifyCompletionActualEffortCmd( c, date, actual ); |
3531 | cmd->execute(); |
3532 | m->addCommand( cmd ); |
3533 | cmd = new ModifyCompletionRemainingEffortCmd( c, date, planned - actual ); |
3534 | cmd->execute(); |
3535 | m->addCommand( cmd ); |
3536 | } |
3537 | return true; |
3538 | } |
3539 | if ( node->type() == Node::Type_Milestone ) { |
3540 | Completion &c = static_cast<Task*>( node )->completion(); |
3541 | if ( value.toInt() > 0 ) { |
3542 | QDateTime dt = QDateTime::currentDateTime(); |
3543 | QDate date = dt.date(); |
3544 | MacroCommand *m = new MacroCommand( kundo2_i18n( "Set finished" ) ); |
3545 | m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); |
3546 | m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); |
3547 | m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); |
3548 | m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); |
3549 | m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, 100 ) ); |
3550 | emit executeCommand( m ); // also adds a new entry if necessary |
3551 | return true; |
3552 | } |
3553 | return false; |
3554 | } |
3555 | return false; |
3556 | } |
3557 | |
3558 | QVariant NodeItemModel::data( const QModelIndex &index, int role ) const |
3559 | { |
3560 | if ( role == Qt::TextAlignmentRole ) { |
3561 | return headerData( index.column(), Qt::Horizontal, role ); |
3562 | } |
3563 | Node *n = node( index ); |
3564 | if ( role == Role::Object ) { |
3565 | return n ? QVariant::fromValue( static_cast<QObject*>( n ) ) : QVariant(); |
3566 | } |
3567 | QVariant result; |
3568 | if ( n != 0 ) { |
3569 | result = m_nodemodel.data( n, index.column(), role ); |
3570 | //kDebug(planDbg())<<n->name()<<": "<<index.column()<<", "<<role<<result; |
3571 | } |
3572 | if ( role == Qt::EditRole ) { |
3573 | switch ( index.column() ) { |
3574 | case NodeModel::NodeActualStart: |
3575 | case NodeModel::NodeActualFinish: |
3576 | if ( ! result.isValid() ) { |
3577 | return QDateTime::currentDateTime(); |
3578 | } |
3579 | break; |
3580 | } |
3581 | } |
3582 | return result; |
3583 | } |
3584 | |
3585 | bool NodeItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) |
3586 | { |
3587 | if ( ! index.isValid() ) { |
3588 | return ItemModelBase::setData( index, value, role ); |
3589 | } |
3590 | if ( ( flags(index) &Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) { |
3591 | kWarning()<<index<<value<<role; |
3592 | return false; |
3593 | } |
3594 | Node *n = node( index ); |
3595 | if ( n ) { |
3596 | switch ( index.column() ) { |
3597 | case NodeModel::NodeCompleted: return setCompletion( n, value, role ); |
3598 | case NodeModel::NodeAllocation: return setAllocation( n, value, role ); |
3599 | default: { |
3600 | KUndo2Command *c = m_nodemodel.setData( n, index.column(), value, role ); |
3601 | if ( c ) { |
3602 | emit executeCommand( c ); |
3603 | return true; |
3604 | } |
3605 | break; |
3606 | } |
3607 | } |
3608 | } |
3609 | return false; |
3610 | } |
3611 | |
3612 | QVariant NodeItemModel::( int section, Qt::Orientation orientation, int role ) const |
3613 | { |
3614 | if ( orientation == Qt::Horizontal ) { |
3615 | if ( role == Qt::DisplayRole || role == Qt::TextAlignmentRole ) { |
3616 | return m_nodemodel.headerData( section, role ); |
3617 | } |
3618 | } |
3619 | if ( role == Qt::ToolTipRole ) { |
3620 | return NodeModel::headerData( section, role ); |
3621 | } else if ( role == Qt::WhatsThisRole ) { |
3622 | return NodeModel::headerData( section, role ); |
3623 | } |
3624 | return ItemModelBase::headerData(section, orientation, role); |
3625 | } |
3626 | |
3627 | QAbstractItemDelegate *NodeItemModel::createDelegate( int column, QWidget *parent ) const |
3628 | { |
3629 | switch ( column ) { |
3630 | //case NodeModel::NodeAllocation: return new ??Delegate( parent ); |
3631 | case NodeModel::NodeEstimateType: return new EnumDelegate( parent ); |
3632 | case NodeModel::NodeEstimateCalendar: return new EnumDelegate( parent ); |
3633 | case NodeModel::NodeEstimate: return new DurationSpinBoxDelegate( parent ); |
3634 | case NodeModel::NodeOptimisticRatio: return new SpinBoxDelegate( parent ); |
3635 | case NodeModel::NodePessimisticRatio: return new SpinBoxDelegate( parent ); |
3636 | case NodeModel::NodeRisk: return new EnumDelegate( parent ); |
3637 | case NodeModel::NodeConstraint: return new EnumDelegate( parent ); |
3638 | case NodeModel::NodeConstraintStart: return new DateTimeCalendarDelegate( parent ); |
3639 | case NodeModel::NodeConstraintEnd: return new DateTimeCalendarDelegate( parent ); |
3640 | case NodeModel::NodeRunningAccount: return new EnumDelegate( parent ); |
3641 | case NodeModel::NodeStartupAccount: return new EnumDelegate( parent ); |
3642 | case NodeModel::NodeStartupCost: return new MoneyDelegate( parent ); |
3643 | case NodeModel::NodeShutdownAccount: return new EnumDelegate( parent ); |
3644 | case NodeModel::NodeShutdownCost: return new MoneyDelegate( parent ); |
3645 | |
3646 | case NodeModel::NodeCompleted: return new TaskCompleteDelegate( parent ); |
3647 | case NodeModel::NodeRemainingEffort: return new DurationSpinBoxDelegate( parent ); |
3648 | case NodeModel::NodeActualEffort: return new DurationSpinBoxDelegate( parent ); |
3649 | |
3650 | default: return 0; |
3651 | } |
3652 | return 0; |
3653 | } |
3654 | |
3655 | int NodeItemModel::columnCount( const QModelIndex &/*parent*/ ) const |
3656 | { |
3657 | return m_nodemodel.propertyCount(); |
3658 | } |
3659 | |
3660 | int NodeItemModel::rowCount( const QModelIndex &parent ) const |
3661 | { |
3662 | if ( m_projectshown && ! parent.isValid() ) { |
3663 | return m_project == 0 ? 0 : 1; |
3664 | } |
3665 | Node *p = node( parent ); |
3666 | return p == 0 ? 0 : p->numChildren(); |
3667 | } |
3668 | |
3669 | Qt::DropActions NodeItemModel::supportedDropActions() const |
3670 | { |
3671 | return Qt::CopyAction | Qt::MoveAction; |
3672 | } |
3673 | |
3674 | |
3675 | QStringList NodeItemModel::mimeTypes() const |
3676 | { |
3677 | return QStringList() << "application/x-vnd.kde.plan.nodeitemmodel.internal" |
3678 | << "application/x-vnd.kde.plan.resourceitemmodel.internal" |
3679 | << "application/x-vnd.kde.plan.project" |
3680 | << "text/uri-list" ; |
3681 | } |
3682 | |
3683 | QMimeData *NodeItemModel::mimeData( const QModelIndexList & indexes ) const |
3684 | { |
3685 | QMimeData *m = new QMimeData(); |
3686 | QByteArray encodedData; |
3687 | QDataStream stream(&encodedData, QIODevice::WriteOnly); |
3688 | QList<int> rows; |
3689 | foreach (const QModelIndex &index, indexes) { |
3690 | if ( index.isValid() && !rows.contains( index.row() ) ) { |
3691 | //kDebug(planDbg())<<index.row(); |
3692 | Node *n = node( index ); |
3693 | if ( n ) { |
3694 | rows << index.row(); |
3695 | stream << n->id(); |
3696 | } |
3697 | } |
3698 | } |
3699 | m->setData("application/x-vnd.kde.plan.nodeitemmodel.internal" , encodedData); |
3700 | return m; |
3701 | } |
3702 | |
3703 | bool NodeItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ) |
3704 | { |
3705 | kDebug(planDbg()); |
3706 | if ( m_projectshown && ! index.isValid() ) { |
3707 | return false; |
3708 | } |
3709 | Node *dn = node( index ); // returns project if ! index.isValid() |
3710 | if ( dn == 0 ) { |
3711 | kError()<<"no node (or project) to drop on!" ; |
3712 | return false; // hmmm |
3713 | } |
3714 | if ( data->hasFormat("application/x-vnd.kde.plan.resourceitemmodel.internal" ) ) { |
3715 | switch ( dropIndicatorPosition ) { |
3716 | case ItemModelBase::OnItem: |
3717 | if ( index.column() == NodeModel::NodeAllocation ) { |
3718 | kDebug(planDbg())<<"resource:" <<index<<(dn->type() == Node::Type_Task); |
3719 | return dn->type() == Node::Type_Task; |
3720 | } else if ( index.column() == NodeModel::NodeResponsible ) { |
3721 | kDebug(planDbg())<<"resource:" <<index<<true; |
3722 | return true; |
3723 | } |
3724 | break; |
3725 | default: |
3726 | break; |
3727 | } |
3728 | } else if ( data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) |
3729 | || data->hasFormat( "application/x-vnd.kde.plan.project" ) |
3730 | || data->hasUrls() ) |
3731 | { |
3732 | switch ( dropIndicatorPosition ) { |
3733 | case ItemModelBase::AboveItem: |
3734 | case ItemModelBase::BelowItem: |
3735 | // dn == sibling, if not project |
3736 | if ( dn == m_project ) { |
3737 | return dropAllowed( dn, data ); |
3738 | } |
3739 | return dropAllowed( dn->parentNode(), data ); |
3740 | case ItemModelBase::OnItem: |
3741 | // dn == new parent |
3742 | return dropAllowed( dn, data ); |
3743 | default: |
3744 | break; |
3745 | } |
3746 | } else { |
3747 | kDebug(planDbg())<<"Unknown mimetype" ; |
3748 | } |
3749 | return false; |
3750 | } |
3751 | |
3752 | QList<Resource*> NodeItemModel::resourceList( QDataStream &stream ) |
3753 | { |
3754 | QList<Resource*> lst; |
3755 | while (!stream.atEnd()) { |
3756 | QString id; |
3757 | stream >> id; |
3758 | kDebug(planDbg())<<"id" <<id; |
3759 | Resource *r = m_project->findResource( id ); |
3760 | if ( r ) { |
3761 | lst << r; |
3762 | } |
3763 | } |
3764 | kDebug(planDbg())<<lst; |
3765 | return lst; |
3766 | } |
3767 | |
3768 | bool NodeItemModel::dropAllowed( Node *on, const QMimeData *data ) |
3769 | { |
3770 | if ( ! m_projectshown && on == m_project ) { |
3771 | return true; |
3772 | } |
3773 | if ( on->isBaselined() && on->type() != Node::Type_Summarytask ) { |
3774 | return false; |
3775 | } |
3776 | if ( data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { |
3777 | QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); |
3778 | QDataStream stream(&encodedData, QIODevice::ReadOnly); |
3779 | QList<Node*> lst = nodeList( stream ); |
3780 | foreach ( Node *n, lst ) { |
3781 | if ( n->type() == Node::Type_Project || on == n || on->isChildOf( n ) ) { |
3782 | return false; |
3783 | } |
3784 | } |
3785 | lst = removeChildNodes( lst ); |
3786 | foreach ( Node *n, lst ) { |
3787 | if ( ! m_project->canMoveTask( n, on ) ) { |
3788 | return false; |
3789 | } |
3790 | } |
3791 | } |
3792 | return true; |
3793 | } |
3794 | |
3795 | QList<Node*> NodeItemModel::nodeList( QDataStream &stream ) |
3796 | { |
3797 | QList<Node*> lst; |
3798 | while (!stream.atEnd()) { |
3799 | QString id; |
3800 | stream >> id; |
3801 | Node *node = m_project->findNode( id ); |
3802 | if ( node ) { |
3803 | lst << node; |
3804 | } |
3805 | } |
3806 | return lst; |
3807 | } |
3808 | |
3809 | QList<Node*> NodeItemModel::removeChildNodes( const QList<Node*> &nodes ) |
3810 | { |
3811 | QList<Node*> lst; |
3812 | foreach ( Node *node, nodes ) { |
3813 | bool ins = true; |
3814 | foreach ( Node *n, lst ) { |
3815 | if ( node->isChildOf( n ) ) { |
3816 | //kDebug(planDbg())<<node->name()<<" is child of"<<n->name(); |
3817 | ins = false; |
3818 | break; |
3819 | } |
3820 | } |
3821 | if ( ins ) { |
3822 | //kDebug(planDbg())<<" insert"<<node->name(); |
3823 | lst << node; |
3824 | } |
3825 | } |
3826 | QList<Node*> nl = lst; |
3827 | QList<Node*> nlst = lst; |
3828 | foreach ( Node *node, nl ) { |
3829 | foreach ( Node *n, nlst ) { |
3830 | if ( n->isChildOf( node ) ) { |
3831 | //kDebug(planDbg())<<n->name()<<" is child of"<<node->name(); |
3832 | int i = nodes.indexOf( n ); |
3833 | lst.removeAt( i ); |
3834 | } |
3835 | } |
3836 | } |
3837 | return lst; |
3838 | } |
3839 | |
3840 | bool NodeItemModel::dropResourceMimeData( const QMimeData *data, Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent ) |
3841 | { |
3842 | QByteArray encodedData = data->data( "application/x-vnd.kde.plan.resourceitemmodel.internal" ); |
3843 | QDataStream stream(&encodedData, QIODevice::ReadOnly); |
3844 | Node *n = node( parent ); |
3845 | kDebug(planDbg())<<n<<parent; |
3846 | if ( n == 0 ) { |
3847 | return true; |
3848 | } |
3849 | kDebug(planDbg())<<n->name(); |
3850 | if ( parent.column() == NodeModel::NodeResponsible ) { |
3851 | QString s; |
3852 | foreach ( Resource *r, resourceList( stream ) ) { |
3853 | s += r->name(); |
3854 | } |
3855 | if ( ! s.isEmpty() ) { |
3856 | if ( action == Qt::CopyAction && ! n->leader().isEmpty() ) { |
3857 | s += ',' + n->leader(); |
3858 | } |
3859 | KUndo2Command *cmd = m_nodemodel.setLeader( n, s, Qt::EditRole ); |
3860 | if ( cmd ) { |
3861 | emit executeCommand( cmd ); |
3862 | } |
3863 | kDebug(planDbg())<<s; |
3864 | } |
3865 | return true; |
3866 | } |
3867 | if ( n->type() == Node::Type_Task ) { |
3868 | QList<Resource*> lst = resourceList( stream ); |
3869 | if ( action == Qt::CopyAction ) { |
3870 | lst += static_cast<Task*>( n )->requestedResources(); |
3871 | } |
3872 | KUndo2Command *cmd = createAllocationCommand( static_cast<Task&>( *n ), lst ); |
3873 | if ( cmd ) { |
3874 | emit executeCommand( cmd ); |
3875 | } |
3876 | return true; |
3877 | } |
3878 | return true; |
3879 | } |
3880 | |
3881 | bool NodeItemModel::dropProjectMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent ) |
3882 | { |
3883 | Node *n = node( parent ); |
3884 | kDebug(planDbg())<<n<<parent; |
3885 | if ( n == 0 ) { |
3886 | n = m_project; |
3887 | } |
3888 | kDebug(planDbg())<<n->name()<<action<<row<<parent; |
3889 | |
3890 | KoXmlDocument doc; |
3891 | doc.setContent( data->data( "application/x-vnd.kde.plan.project" ) ); |
3892 | KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); |
3893 | Project project; |
3894 | XMLLoaderObject status; |
3895 | status.setVersion( doc.documentElement().attribute( "version" , PLAN_FILE_SYNTAX_VERSION ) ); |
3896 | status.setProject( &project ); |
3897 | if ( ! project.load( element, status ) ) { |
3898 | kDebug(planDbg())<<"Failed to load project" ; |
3899 | return false; |
3900 | } |
3901 | project.generateUniqueNodeIds(); |
3902 | KUndo2Command *cmd = new InsertProjectCmd( project, n, n->childNode( row - 1 ), kundo2_i18nc("1=project or task name" , "Insert %1" , project.name() ) ); |
3903 | emit executeCommand( cmd ); |
3904 | return true; |
3905 | } |
3906 | |
3907 | bool NodeItemModel::dropUrlMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) |
3908 | { |
3909 | if ( data->hasUrls() ) { |
3910 | QList<QUrl> urls = data->urls(); |
3911 | kDebug(planDbg())<<urls; |
3912 | foreach ( const QUrl &url, urls ) { |
3913 | KMimeType::Ptr mime = KMimeType::findByUrl( url ); |
3914 | kDebug(planDbg())<<url<<mime->name(); |
3915 | if ( mime->is( "application/x-vnd.kde.plan" ) ) { |
3916 | importProjectFile( url, action, row, column, parent ); |
3917 | } |
3918 | } |
3919 | return true; |
3920 | } |
3921 | return false; |
3922 | } |
3923 | |
3924 | bool NodeItemModel::importProjectFile( const KUrl &url, Qt::DropAction /*action*/, int row, int /*column*/, const QModelIndex &parent ) |
3925 | { |
3926 | if ( ! url.isLocalFile() ) { |
3927 | kDebug(planDbg())<<"TODO: download if url not local" ; |
3928 | return false; |
3929 | } |
3930 | KoStore *store = KoStore::createStore( url.path(), KoStore::Read, "" , KoStore::Auto ); |
3931 | if ( store->bad() ) { |
3932 | // d->lastErrorMessage = i18n( "Not a valid Calligra file: %1", file ); |
3933 | kDebug(planDbg())<<"bad store" <<url.prettyUrl(); |
3934 | delete store; |
3935 | // QApplication::restoreOverrideCursor(); |
3936 | return false; |
3937 | } |
3938 | if ( ! store->open( "root" ) ) { // maindoc.xml |
3939 | kDebug(planDbg())<<"No root" <<url.prettyUrl(); |
3940 | delete store; |
3941 | return false; |
3942 | } |
3943 | KoXmlDocument doc; |
3944 | doc.setContent( store->device() ); |
3945 | KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); |
3946 | Project project; |
3947 | XMLLoaderObject status; |
3948 | status.setVersion( doc.documentElement().attribute( "version" , PLAN_FILE_SYNTAX_VERSION ) ); |
3949 | status.setProject( &project ); |
3950 | if ( ! project.load( element, status ) ) { |
3951 | kDebug(planDbg())<<"Failed to load project from:" <<url; |
3952 | return false; |
3953 | } |
3954 | project.generateUniqueNodeIds(); |
3955 | Node *n = node( parent ); |
3956 | kDebug(planDbg())<<n<<parent; |
3957 | if ( n == 0 ) { |
3958 | n = m_project; |
3959 | } |
3960 | KUndo2Command *cmd = new InsertProjectCmd( project, n, n->childNode( row - 1 ), kundo2_i18n( "Insert %1" , url.fileName() ) ); |
3961 | emit executeCommand( cmd ); |
3962 | return true; |
3963 | } |
3964 | |
3965 | KUndo2Command *NodeItemModel::createAllocationCommand( Task &task, const QList<Resource*> &lst ) |
3966 | { |
3967 | MacroCommand *cmd = new MacroCommand( kundo2_i18n( "Modify resource allocations" ) ); |
3968 | QMap<ResourceGroup*, ResourceGroupRequest*> groups; |
3969 | foreach ( Resource *r, lst ) { |
3970 | if ( ! groups.contains( r->parentGroup() ) && task.resourceGroupRequest( r->parentGroup() ) == 0 ) { |
3971 | ResourceGroupRequest *gr = new ResourceGroupRequest( r->parentGroup() ); |
3972 | groups[ r->parentGroup() ] = gr; |
3973 | cmd->addCommand( new AddResourceGroupRequestCmd( task, gr ) ); |
3974 | } |
3975 | } |
3976 | QList<Resource*> resources = task.requestedResources(); |
3977 | foreach ( Resource *r, lst ) { |
3978 | if ( resources.contains( r ) ) { |
3979 | continue; |
3980 | } |
3981 | ResourceGroupRequest *gr = groups.value( r->parentGroup() ); |
3982 | if ( gr == 0 ) { |
3983 | gr = task.resourceGroupRequest( r->parentGroup() ); |
3984 | } |
3985 | if ( gr == 0 ) { |
3986 | kError()<<"No group request found, cannot add resource request:" <<r->name(); |
3987 | continue; |
3988 | } |
3989 | cmd->addCommand( new AddResourceRequestCmd( gr, new ResourceRequest( r, 100 ) ) ); |
3990 | } |
3991 | foreach ( Resource *r, resources ) { |
3992 | if ( ! lst.contains( r ) ) { |
3993 | ResourceGroupRequest *gr = task.resourceGroupRequest( r->parentGroup() ); |
3994 | ResourceRequest *rr = task.requests().find( r ); |
3995 | if ( gr && rr ) { |
3996 | cmd->addCommand( new RemoveResourceRequestCmd( gr, rr ) ); |
3997 | } |
3998 | } |
3999 | } |
4000 | if ( cmd->isEmpty() ) { |
4001 | delete cmd; |
4002 | return 0; |
4003 | } |
4004 | return cmd; |
4005 | } |
4006 | |
4007 | bool NodeItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) |
4008 | { |
4009 | kDebug(planDbg())<<action; |
4010 | if (action == Qt::IgnoreAction) { |
4011 | return true; |
4012 | } |
4013 | if ( data->hasFormat( "application/x-vnd.kde.plan.resourceitemmodel.internal" ) ) { |
4014 | return dropResourceMimeData( data, action, row, column, parent ); |
4015 | } |
4016 | if ( data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { |
4017 | if ( action == Qt::MoveAction ) { |
4018 | //kDebug(planDbg())<<"MoveAction"; |
4019 | |
4020 | QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); |
4021 | QDataStream stream(&encodedData, QIODevice::ReadOnly); |
4022 | Node *par = 0; |
4023 | if ( parent.isValid() ) { |
4024 | par = node( parent ); |
4025 | } else { |
4026 | par = m_project; |
4027 | } |
4028 | QList<Node*> lst = nodeList( stream ); |
4029 | QList<Node*> nodes = removeChildNodes( lst ); // children goes with their parent |
4030 | foreach ( Node *n, nodes ) { |
4031 | if ( ! m_project->canMoveTask( n, par ) ) { |
4032 | //kDebug(planDbg())<<"Can't move task:"<<n->name(); |
4033 | return false; |
4034 | } |
4035 | } |
4036 | int offset = 0; |
4037 | MacroCommand *cmd = 0; |
4038 | foreach ( Node *n, nodes ) { |
4039 | if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Move tasks" ) ); |
4040 | // append nodes if dropped *on* another node, insert if dropped *after* |
4041 | int pos = row == -1 ? -1 : row + offset; |
4042 | if ( pos >= 0 && n->parentNode() == par && par->indexOf( n ) < pos ) { |
4043 | --pos; |
4044 | } |
4045 | cmd->addCommand( new NodeMoveCmd( m_project, n, par, pos ) ); |
4046 | offset++; |
4047 | } |
4048 | if ( cmd ) { |
4049 | emit executeCommand( cmd ); |
4050 | } |
4051 | //kDebug(planDbg())<<row<<","<<column<<" parent="<<parent.row()<<","<<parent.column()<<":"<<par->name(); |
4052 | return true; |
4053 | } |
4054 | } |
4055 | if ( data->hasFormat( "application/x-vnd.kde.plan.project" ) ) { |
4056 | kDebug(planDbg()); |
4057 | return dropProjectMimeData( data, action, row, column, parent ); |
4058 | |
4059 | } |
4060 | if ( data->hasUrls() ) { |
4061 | return dropUrlMimeData( data, action, row, column, parent ); |
4062 | } |
4063 | return false; |
4064 | } |
4065 | |
4066 | Node *NodeItemModel::node( const QModelIndex &index ) const |
4067 | { |
4068 | Node *n = m_project; |
4069 | if ( index.isValid() ) { |
4070 | //kDebug(planDbg())<<index.internalPointer()<<":"<<index.row()<<","<<index.column(); |
4071 | n = static_cast<Node*>( index.internalPointer() ); |
4072 | Q_ASSERT( n ); |
4073 | } |
4074 | return n; |
4075 | } |
4076 | |
4077 | void NodeItemModel::slotNodeChanged( Node *node ) |
4078 | { |
4079 | if ( node == 0 || ( ! m_projectshown && node->type() == Node::Type_Project ) ) { |
4080 | return; |
4081 | } |
4082 | if ( node->type() == Node::Type_Project ) { |
4083 | emit dataChanged( createIndex( 0, 0, node ), createIndex( 0, columnCount()-1, node ) ); |
4084 | return; |
4085 | } |
4086 | int row = node->parentNode()->findChildNode( node ); |
4087 | Q_ASSERT( row >= 0 ); |
4088 | emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount()-1, node ) ); |
4089 | } |
4090 | |
4091 | QModelIndex NodeItemModel::insertTask( Node *node, Node *after ) |
4092 | { |
4093 | MacroCommand *cmd = new MacroCommand( kundo2_i18n( "Add task" ) ); |
4094 | cmd->addCommand( new TaskAddCmd( m_project, node, after ) ); |
4095 | if ( m_project && node->type() == Node::Type_Task ) { |
4096 | QMap<ResourceGroup*, ResourceGroupRequest*> groups; |
4097 | foreach ( Resource *r, m_project->autoAllocateResources() ) { |
4098 | if ( ! groups.contains( r->parentGroup() ) ) { |
4099 | ResourceGroupRequest *gr = new ResourceGroupRequest( r->parentGroup() ); |
4100 | cmd->addCommand( new AddResourceGroupRequestCmd( static_cast<Task&>(*node), gr ) ); |
4101 | groups[ r->parentGroup() ] = gr; |
4102 | } |
4103 | ResourceRequest *rr = new ResourceRequest( r, 100 ); |
4104 | cmd->addCommand( new AddResourceRequestCmd( groups[ r->parentGroup() ], rr ) ); |
4105 | } |
4106 | } |
4107 | emit executeCommand( cmd ); |
4108 | int row = -1; |
4109 | if ( node->parentNode() ) { |
4110 | row = node->parentNode()->indexOf( node ); |
4111 | } |
4112 | if ( row != -1 ) { |
4113 | //kDebug(planDbg())<<"Inserted: "<<node->name()<<"; "<<row; |
4114 | return createIndex( row, 0, node ); |
4115 | } |
4116 | //kDebug(planDbg())<<"Can't find "<<node->name(); |
4117 | return QModelIndex(); |
4118 | } |
4119 | |
4120 | QModelIndex NodeItemModel::insertSubtask( Node *node, Node *parent ) |
4121 | { |
4122 | emit executeCommand( new SubtaskAddCmd( m_project, node, parent, kundo2_i18n( "Add sub-task" ) ) ); |
4123 | int row = -1; |
4124 | if ( node->parentNode() ) { |
4125 | row = node->parentNode()->indexOf( node ); |
4126 | } |
4127 | if ( row != -1 ) { |
4128 | //kDebug(planDbg())<<node->parentNode()<<" inserted: "<<node->name()<<"; "<<row; |
4129 | return createIndex( row, 0, node ); |
4130 | } |
4131 | //kDebug(planDbg())<<"Can't find "<<node->name(); |
4132 | return QModelIndex(); |
4133 | } |
4134 | |
4135 | int NodeItemModel::sortRole( int column ) const |
4136 | { |
4137 | switch ( column ) { |
4138 | case NodeModel::NodeStartTime: |
4139 | case NodeModel::NodeEndTime: |
4140 | case NodeModel::NodeActualStart: |
4141 | case NodeModel::NodeActualFinish: |
4142 | case NodeModel::NodeEarlyStart: |
4143 | case NodeModel::NodeEarlyFinish: |
4144 | case NodeModel::NodeLateStart: |
4145 | case NodeModel::NodeLateFinish: |
4146 | case NodeModel::NodeConstraintStart: |
4147 | case NodeModel::NodeConstraintEnd: |
4148 | return Qt::EditRole; |
4149 | default: |
4150 | break; |
4151 | } |
4152 | return Qt::DisplayRole; |
4153 | } |
4154 | |
4155 | //------------------------------------------------ |
4156 | GanttItemModel::GanttItemModel( QObject *parent ) |
4157 | : NodeItemModel( parent ), |
4158 | m_showSpecial( false ) |
4159 | { |
4160 | } |
4161 | |
4162 | GanttItemModel::~GanttItemModel() |
4163 | { |
4164 | QList<void*> lst = parentmap.values(); |
4165 | while ( ! lst.isEmpty() ) |
4166 | delete (int*)(lst.takeFirst()); |
4167 | } |
4168 | |
4169 | int GanttItemModel::rowCount( const QModelIndex &parent ) const |
4170 | { |
4171 | if ( m_showSpecial ) { |
4172 | if ( parentmap.values().contains( parent.internalPointer() ) ) { |
4173 | return 0; |
4174 | } |
4175 | Node *n = node( parent ); |
4176 | if ( n && n->type() == Node::Type_Task ) { |
4177 | return 5; // the task + early start + late finish ++ |
4178 | } |
4179 | } |
4180 | return NodeItemModel::rowCount( parent ); |
4181 | } |
4182 | |
4183 | QModelIndex GanttItemModel::index( int row, int column, const QModelIndex &parent ) const |
4184 | { |
4185 | if ( m_showSpecial && parent.isValid() ) { |
4186 | Node *p = node( parent ); |
4187 | if ( p->type() == Node::Type_Task ) { |
4188 | void *v = 0; |
4189 | foreach ( void *i, parentmap.values( p ) ) { |
4190 | if ( *( (int*)( i ) ) == row ) { |
4191 | v = i; |
4192 | break; |
4193 | } |
4194 | } |
4195 | if ( v == 0 ) { |
4196 | v = new int( row ); |
4197 | const_cast<GanttItemModel*>( this )->parentmap.insertMulti( p, v ); |
4198 | } |
4199 | return createIndex( row, column, v ); |
4200 | } |
4201 | } |
4202 | return NodeItemModel::index( row, column, parent ); |
4203 | } |
4204 | |
4205 | QModelIndex GanttItemModel::parent( const QModelIndex &idx ) const |
4206 | { |
4207 | if ( m_showSpecial ) { |
4208 | QList<Node*> lst = parentmap.keys( idx.internalPointer() ); |
4209 | if ( ! lst.isEmpty() ) { |
4210 | Q_ASSERT( lst.count() == 1 ); |
4211 | return index( lst.first() ); |
4212 | } |
4213 | } |
4214 | return NodeItemModel::parent( idx ); |
4215 | } |
4216 | |
4217 | QVariant GanttItemModel::data( const QModelIndex &index, int role ) const |
4218 | { |
4219 | if ( ! index.isValid() ) { |
4220 | return QVariant(); |
4221 | } |
4222 | if ( role == Qt::TextAlignmentRole ) { |
4223 | return headerData( index.column(), Qt::Horizontal, role ); |
4224 | } |
4225 | QModelIndex idx = index; |
4226 | QList<Node*> lst; |
4227 | if ( m_showSpecial ) { |
4228 | lst = parentmap.keys( idx.internalPointer() ); |
4229 | } |
4230 | if ( ! lst.isEmpty() ) { |
4231 | Q_ASSERT( lst.count() == 1 ); |
4232 | int row = *((int*)(idx.internalPointer())); |
4233 | Node *n = lst.first(); |
4234 | if ( role == SpecialItemTypeRole ) { |
4235 | return row; // 0=task, 1=early start, 2=late finish... |
4236 | } |
4237 | switch ( row ) { |
4238 | case 0: // the task |
4239 | if ( idx.column() == NodeModel::NodeType && role == KDGantt::ItemTypeRole ) { |
4240 | switch ( n->type() ) { |
4241 | case Node::Type_Task: return KDGantt::TypeTask; |
4242 | default: break; |
4243 | } |
4244 | } |
4245 | break; |
4246 | case 1: { // early start |
4247 | if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KDGantt::ItemTypeRole ) { |
4248 | return QVariant(); |
4249 | } |
4250 | switch ( idx.column() ) { |
4251 | case NodeModel::NodeName: return "Early Start" ; |
4252 | case NodeModel::NodeType: return KDGantt::TypeEvent; |
4253 | case NodeModel::NodeStartTime: |
4254 | case NodeModel::NodeEndTime: return n->earlyStart( id() ); |
4255 | default: break; |
4256 | } |
4257 | } |
4258 | case 2: { // late finish |
4259 | if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KDGantt::ItemTypeRole ) { |
4260 | return QVariant(); |
4261 | } |
4262 | switch ( idx.column() ) { |
4263 | case NodeModel::NodeName: return "Late Finish" ; |
4264 | case NodeModel::NodeType: return KDGantt::TypeEvent; |
4265 | case NodeModel::NodeStartTime: |
4266 | case NodeModel::NodeEndTime: return n->lateFinish( id() ); |
4267 | default: break; |
4268 | } |
4269 | } |
4270 | case 3: { // late start |
4271 | if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KDGantt::ItemTypeRole ) { |
4272 | return QVariant(); |
4273 | } |
4274 | switch ( idx.column() ) { |
4275 | case NodeModel::NodeName: return "Late Start" ; |
4276 | case NodeModel::NodeType: return KDGantt::TypeEvent; |
4277 | case NodeModel::NodeStartTime: |
4278 | case NodeModel::NodeEndTime: return n->lateStart( id() ); |
4279 | default: break; |
4280 | } |
4281 | } |
4282 | case 4: { // early finish |
4283 | if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KDGantt::ItemTypeRole ) { |
4284 | return QVariant(); |
4285 | } |
4286 | switch ( idx.column() ) { |
4287 | case NodeModel::NodeName: return "Early Finish" ; |
4288 | case NodeModel::NodeType: return KDGantt::TypeEvent; |
4289 | case NodeModel::NodeStartTime: |
4290 | case NodeModel::NodeEndTime: return n->earlyFinish( id() ); |
4291 | default: break; |
4292 | } |
4293 | } |
4294 | default: return QVariant(); |
4295 | } |
4296 | idx = createIndex( idx.row(), idx.column(), n ); |
4297 | } else { |
4298 | if ( role == SpecialItemTypeRole ) { |
4299 | return 0; // task of some type |
4300 | } |
4301 | if ( idx.column() == NodeModel::NodeType && role == KDGantt::ItemTypeRole ) { |
4302 | QVariant result = NodeItemModel::data( idx, Qt::EditRole ); |
4303 | switch ( result.toInt() ) { |
4304 | case Node::Type_Project: return KDGantt::TypeSummary; |
4305 | case Node::Type_Summarytask: return KDGantt::TypeSummary; |
4306 | case Node::Type_Milestone: return KDGantt::TypeEvent; |
4307 | default: return m_showSpecial ? KDGantt::TypeMulti : KDGantt::TypeTask; |
4308 | } |
4309 | } |
4310 | } |
4311 | return NodeItemModel::data( idx, role ); |
4312 | } |
4313 | |
4314 | //---------------------------- |
4315 | MilestoneItemModel::MilestoneItemModel( QObject *parent ) |
4316 | : ItemModelBase( parent ) |
4317 | { |
4318 | } |
4319 | |
4320 | MilestoneItemModel::~MilestoneItemModel() |
4321 | { |
4322 | } |
4323 | |
4324 | QList<Node*> MilestoneItemModel::mileStones() const |
4325 | { |
4326 | QList<Node*> lst; |
4327 | foreach( Node* n, m_nodemap ) { |
4328 | if ( n->type() == Node::Type_Milestone ) { |
4329 | lst << n; |
4330 | } |
4331 | } |
4332 | return lst; |
4333 | } |
4334 | |
4335 | void MilestoneItemModel::slotNodeToBeInserted( Node *parent, int row ) |
4336 | { |
4337 | Q_UNUSED(parent); |
4338 | Q_UNUSED(row); |
4339 | } |
4340 | |
4341 | void MilestoneItemModel::slotNodeInserted( Node *node ) |
4342 | { |
4343 | Q_UNUSED(node); |
4344 | resetModel(); |
4345 | } |
4346 | |
4347 | void MilestoneItemModel::slotNodeToBeRemoved( Node *node ) |
4348 | { |
4349 | Q_UNUSED(node); |
4350 | //kDebug(planDbg())<<node->name(); |
4351 | /* int row = m_nodemap.values().indexOf( node ); |
4352 | if ( row != -1 ) { |
4353 | Q_ASSERT( m_nodemap.contains( node->wbsCode() ) ); |
4354 | Q_ASSERT( m_nodemap.keys().indexOf( node->wbsCode() ) == row ); |
4355 | beginRemoveRows( QModelIndex(), row, row ); |
4356 | m_nodemap.remove( node->wbsCode() ); |
4357 | endRemoveRows(); |
4358 | }*/ |
4359 | } |
4360 | |
4361 | void MilestoneItemModel::slotNodeRemoved( Node *node ) |
4362 | { |
4363 | Q_UNUSED(node); |
4364 | resetModel(); |
4365 | //endRemoveRows(); |
4366 | } |
4367 | |
4368 | void MilestoneItemModel::slotLayoutChanged() |
4369 | { |
4370 | //kDebug(planDbg())<<node->name(); |
4371 | emit layoutAboutToBeChanged(); |
4372 | emit layoutChanged(); |
4373 | } |
4374 | |
4375 | void MilestoneItemModel::slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ) |
4376 | { |
4377 | Q_UNUSED( node ); |
4378 | Q_UNUSED( pos ); |
4379 | Q_UNUSED( newParent ); |
4380 | Q_UNUSED( newPos ); |
4381 | } |
4382 | |
4383 | void MilestoneItemModel::slotNodeMoved( Node *node ) |
4384 | { |
4385 | Q_UNUSED( node ); |
4386 | resetModel(); |
4387 | } |
4388 | |
4389 | void MilestoneItemModel::setProject( Project *project ) |
4390 | { |
4391 | if ( m_project ) { |
4392 | disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); |
4393 | disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); |
4394 | disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); |
4395 | disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); |
4396 | disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); |
4397 | |
4398 | disconnect(m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int))); |
4399 | disconnect(m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*))); |
4400 | |
4401 | disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); |
4402 | disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); |
4403 | } |
4404 | m_project = project; |
4405 | //kDebug(planDbg())<<m_project<<"->"<<project; |
4406 | m_nodemodel.setProject( project ); |
4407 | if ( project ) { |
4408 | connect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); |
4409 | connect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); |
4410 | connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); |
4411 | connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); |
4412 | connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); |
4413 | |
4414 | connect(m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int))); |
4415 | connect(m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*))); |
4416 | |
4417 | connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); |
4418 | connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); |
4419 | } |
4420 | resetModel(); |
4421 | } |
4422 | |
4423 | void MilestoneItemModel::setScheduleManager( ScheduleManager *sm ) |
4424 | { |
4425 | if ( m_nodemodel.manager() ) { |
4426 | } |
4427 | m_nodemodel.setManager( sm ); |
4428 | ItemModelBase::setScheduleManager( sm ); |
4429 | if ( sm ) { |
4430 | } |
4431 | //kDebug(planDbg())<<sm; |
4432 | resetModel(); |
4433 | } |
4434 | |
4435 | bool MilestoneItemModel::resetData() |
4436 | { |
4437 | int cnt = m_nodemap.count(); |
4438 | m_nodemap.clear(); |
4439 | if ( m_project != 0 ) { |
4440 | foreach ( Node *n, m_project->allNodes() ) { |
4441 | m_nodemap.insert( n->wbsCode(), n ); |
4442 | } |
4443 | } |
4444 | return cnt != m_nodemap.count(); |
4445 | } |
4446 | |
4447 | void MilestoneItemModel::resetModel() |
4448 | { |
4449 | resetData(); |
4450 | reset(); |
4451 | } |
4452 | |
4453 | Qt::ItemFlags MilestoneItemModel::flags( const QModelIndex &index ) const |
4454 | { |
4455 | Qt::ItemFlags flags = QAbstractItemModel::flags( index ); |
4456 | if ( !index.isValid() ) { |
4457 | if ( m_readWrite ) { |
4458 | flags |= Qt::ItemIsDropEnabled; |
4459 | } |
4460 | return flags; |
4461 | } |
4462 | if ( m_readWrite ) { |
4463 | flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; |
4464 | switch ( index.column() ) { |
4465 | case NodeModel::NodeName: // name |
4466 | flags |= Qt::ItemIsEditable; |
4467 | break; |
4468 | case NodeModel::NodeType: break; // Node type |
4469 | case NodeModel::NodeResponsible: // Responsible |
4470 | flags |= Qt::ItemIsEditable; |
4471 | break; |
4472 | case NodeModel::NodeConstraint: // constraint type |
4473 | flags |= Qt::ItemIsEditable; |
4474 | break; |
4475 | case NodeModel::NodeConstraintStart: { // constraint start |
4476 | Node *n = node( index ); |
4477 | if ( n == 0 ) |
4478 | break; |
4479 | int c = n->constraint(); |
4480 | if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) { |
4481 | flags |= Qt::ItemIsEditable; |
4482 | } |
4483 | break; |
4484 | } |
4485 | case NodeModel::NodeConstraintEnd: { // constraint end |
4486 | Node *n = node( index ); |
4487 | if ( n == 0 ) |
4488 | break; |
4489 | int c = n->constraint(); |
4490 | if ( c == Node::MustFinishOn || c == Node::FinishNotLater || c == Node::FixedInterval ) { |
4491 | flags |= Qt::ItemIsEditable; |
4492 | } |
4493 | break; |
4494 | } |
4495 | case NodeModel::NodeStartupAccount: // startup account |
4496 | case NodeModel::NodeStartupCost: // startup cost |
4497 | case NodeModel::NodeShutdownAccount: // shutdown account |
4498 | case NodeModel::NodeShutdownCost: { // shutdown cost |
4499 | Node *n = node( index ); |
4500 | if ( n && (n->type() == Node::Type_Task || n->type() == Node::Type_Milestone) ) { |
4501 | flags |= Qt::ItemIsEditable; |
4502 | } |
4503 | break; |
4504 | } |
4505 | case NodeModel::NodeDescription: // description |
4506 | break; |
4507 | default: |
4508 | flags &= ~Qt::ItemIsEditable; |
4509 | } |
4510 | } |
4511 | return flags; |
4512 | } |
4513 | |
4514 | QModelIndex MilestoneItemModel::parent( const QModelIndex &index ) const |
4515 | { |
4516 | Q_UNUSED(index); |
4517 | return QModelIndex(); |
4518 | } |
4519 | |
4520 | QModelIndex MilestoneItemModel::index( int row, int column, const QModelIndex &parent ) const |
4521 | { |
4522 | //kDebug(planDbg())<<parent<<row<<", "<<m_nodemap.count(); |
4523 | if ( m_project == 0 || row < 0 || column < 0 ) { |
4524 | //kDebug(planDbg())<<"No project"<<m_project<<" or illegal row, column"<<row<<column; |
4525 | return QModelIndex(); |
4526 | } |
4527 | if ( parent.isValid() || row >= m_nodemap.count() ) { |
4528 | //kDebug(planDbg())<<"No index for"<<parent<<row<<","<<column; |
4529 | return QModelIndex(); |
4530 | } |
4531 | return createIndex( row, column, m_nodemap.values().at( row ) ); |
4532 | } |
4533 | |
4534 | QModelIndex MilestoneItemModel::index( const Node *node ) const |
4535 | { |
4536 | if ( m_project == 0 || node == 0 ) { |
4537 | return QModelIndex(); |
4538 | } |
4539 | return createIndex( m_nodemap.values().indexOf( const_cast<Node*>( node ) ), 0, const_cast<Node*>(node) ); |
4540 | } |
4541 | |
4542 | |
4543 | QVariant MilestoneItemModel::data( const QModelIndex &index, int role ) const |
4544 | { |
4545 | QVariant result; |
4546 | if ( role == Qt::TextAlignmentRole ) { |
4547 | return headerData( index.column(), Qt::Horizontal, role ); |
4548 | } |
4549 | Node *n = node( index ); |
4550 | if ( n != 0 ) { |
4551 | if ( index.column() == NodeModel::NodeType && role == KDGantt::ItemTypeRole ) { |
4552 | result = m_nodemodel.data( n, index.column(), Qt::EditRole ); |
4553 | switch ( result.toInt() ) { |
4554 | case Node::Type_Summarytask: return KDGantt::TypeSummary; |
4555 | case Node::Type_Milestone: return KDGantt::TypeEvent; |
4556 | default: return KDGantt::TypeTask; |
4557 | } |
4558 | return result; |
4559 | } |
4560 | } |
4561 | result = m_nodemodel.data( n, index.column(), role ); |
4562 | return result; |
4563 | } |
4564 | |
4565 | bool MilestoneItemModel::setData( const QModelIndex &index, const QVariant &/*value*/, int role ) |
4566 | { |
4567 | if ( ( flags(index) &Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) { |
4568 | return false; |
4569 | } |
4570 | // Node *n = node( index ); |
4571 | switch (index.column()) { |
4572 | default: |
4573 | qWarning("data: invalid display value column %d" , index.column()); |
4574 | return false; |
4575 | } |
4576 | return false; |
4577 | } |
4578 | |
4579 | QVariant MilestoneItemModel::( int section, Qt::Orientation orientation, int role ) const |
4580 | { |
4581 | if ( orientation == Qt::Horizontal ) { |
4582 | if ( role == Qt::DisplayRole || role == Qt::TextAlignmentRole) { |
4583 | return m_nodemodel.headerData( section, role ); |
4584 | } |
4585 | } |
4586 | if ( role == Qt::ToolTipRole ) { |
4587 | return NodeModel::headerData( section, role ); |
4588 | } |
4589 | return ItemModelBase::headerData(section, orientation, role); |
4590 | } |
4591 | |
4592 | QAbstractItemDelegate *MilestoneItemModel::createDelegate( int column, QWidget *parent ) const |
4593 | { |
4594 | switch ( column ) { |
4595 | case NodeModel::NodeEstimateType: return new EnumDelegate( parent ); |
4596 | case NodeModel::NodeEstimateCalendar: return new EnumDelegate( parent ); |
4597 | case NodeModel::NodeEstimate: return new DurationSpinBoxDelegate( parent ); |
4598 | case NodeModel::NodeOptimisticRatio: return new SpinBoxDelegate( parent ); |
4599 | case NodeModel::NodePessimisticRatio: return new SpinBoxDelegate( parent ); |
4600 | case NodeModel::NodeRisk: return new EnumDelegate( parent ); |
4601 | case NodeModel::NodeConstraint: return new EnumDelegate( parent ); |
4602 | case NodeModel::NodeRunningAccount: return new EnumDelegate( parent ); |
4603 | case NodeModel::NodeStartupAccount: return new EnumDelegate( parent ); |
4604 | case NodeModel::NodeStartupCost: return new MoneyDelegate( parent ); |
4605 | case NodeModel::NodeShutdownAccount: return new EnumDelegate( parent ); |
4606 | case NodeModel::NodeShutdownCost: return new MoneyDelegate( parent ); |
4607 | |
4608 | case NodeModel::NodeCompleted: return new TaskCompleteDelegate( parent ); |
4609 | case NodeModel::NodeRemainingEffort: return new DurationSpinBoxDelegate( parent ); |
4610 | case NodeModel::NodeActualEffort: return new DurationSpinBoxDelegate( parent ); |
4611 | |
4612 | default: return 0; |
4613 | } |
4614 | return 0; |
4615 | } |
4616 | |
4617 | int MilestoneItemModel::columnCount( const QModelIndex &/*parent*/ ) const |
4618 | { |
4619 | return m_nodemodel.propertyCount(); |
4620 | } |
4621 | |
4622 | int MilestoneItemModel::rowCount( const QModelIndex &parent ) const |
4623 | { |
4624 | //kDebug(planDbg())<<parent; |
4625 | if ( parent.isValid() ) { |
4626 | return 0; |
4627 | } |
4628 | //kDebug(planDbg())<<m_nodemap.count(); |
4629 | return m_nodemap.count(); |
4630 | } |
4631 | |
4632 | Qt::DropActions MilestoneItemModel::supportedDropActions() const |
4633 | { |
4634 | return Qt::CopyAction | Qt::MoveAction; |
4635 | } |
4636 | |
4637 | |
4638 | QStringList MilestoneItemModel::mimeTypes() const |
4639 | { |
4640 | return QStringList(); |
4641 | } |
4642 | |
4643 | QMimeData *MilestoneItemModel::mimeData( const QModelIndexList & indexes ) const |
4644 | { |
4645 | QMimeData *m = new QMimeData(); |
4646 | QByteArray encodedData; |
4647 | QDataStream stream(&encodedData, QIODevice::WriteOnly); |
4648 | QList<int> rows; |
4649 | foreach (const QModelIndex &index, indexes) { |
4650 | if ( index.isValid() && !rows.contains( index.row() ) ) { |
4651 | //kDebug(planDbg())<<index.row(); |
4652 | Node *n = node( index ); |
4653 | if ( n ) { |
4654 | rows << index.row(); |
4655 | stream << n->id(); |
4656 | } |
4657 | } |
4658 | } |
4659 | m->setData("application/x-vnd.kde.plan.nodeitemmodel.internal" , encodedData); |
4660 | return m; |
4661 | } |
4662 | |
4663 | bool MilestoneItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ) |
4664 | { |
4665 | //kDebug(planDbg()); |
4666 | Node *dn = node( index ); |
4667 | if ( dn == 0 ) { |
4668 | kError()<<"no node to drop on!" ; |
4669 | return false; // hmmm |
4670 | } |
4671 | switch ( dropIndicatorPosition ) { |
4672 | case ItemModelBase::AboveItem: |
4673 | case ItemModelBase::BelowItem: |
4674 | // dn == sibling |
4675 | return dropAllowed( dn->parentNode(), data ); |
4676 | case ItemModelBase::OnItem: |
4677 | // dn == new parent |
4678 | return dropAllowed( dn, data ); |
4679 | default: |
4680 | break; |
4681 | } |
4682 | return false; |
4683 | } |
4684 | |
4685 | bool MilestoneItemModel::dropAllowed( Node *on, const QMimeData *data ) |
4686 | { |
4687 | if ( !data->hasFormat("application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { |
4688 | return false; |
4689 | } |
4690 | if ( on == m_project ) { |
4691 | return true; |
4692 | } |
4693 | QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); |
4694 | QDataStream stream(&encodedData, QIODevice::ReadOnly); |
4695 | QList<Node*> lst = nodeList( stream ); |
4696 | foreach ( Node *n, lst ) { |
4697 | if ( on == n || on->isChildOf( n ) ) { |
4698 | return false; |
4699 | } |
4700 | } |
4701 | lst = removeChildNodes( lst ); |
4702 | foreach ( Node *n, lst ) { |
4703 | if ( ! m_project->canMoveTask( n, on ) ) { |
4704 | return false; |
4705 | } |
4706 | } |
4707 | return true; |
4708 | } |
4709 | |
4710 | QList<Node*> MilestoneItemModel::nodeList( QDataStream &stream ) |
4711 | { |
4712 | QList<Node*> lst; |
4713 | while (!stream.atEnd()) { |
4714 | QString id; |
4715 | stream >> id; |
4716 | Node *node = m_project->findNode( id ); |
4717 | if ( node ) { |
4718 | lst << node; |
4719 | } |
4720 | } |
4721 | return lst; |
4722 | } |
4723 | |
4724 | QList<Node*> MilestoneItemModel::removeChildNodes( const QList<Node*> &nodes ) |
4725 | { |
4726 | QList<Node*> lst; |
4727 | foreach ( Node *node, nodes ) { |
4728 | bool ins = true; |
4729 | foreach ( Node *n, lst ) { |
4730 | if ( node->isChildOf( n ) ) { |
4731 | //kDebug(planDbg())<<node->name()<<" is child of"<<n->name(); |
4732 | ins = false; |
4733 | break; |
4734 | } |
4735 | } |
4736 | if ( ins ) { |
4737 | //kDebug(planDbg())<<" insert"<<node->name(); |
4738 | lst << node; |
4739 | } |
4740 | } |
4741 | QList<Node*> nl = lst; |
4742 | QList<Node*> nlst = lst; |
4743 | foreach ( Node *node, nl ) { |
4744 | foreach ( Node *n, nlst ) { |
4745 | if ( n->isChildOf( node ) ) { |
4746 | //kDebug(planDbg())<<n->name()<<" is child of"<<node->name(); |
4747 | int i = nodes.indexOf( n ); |
4748 | lst.removeAt( i ); |
4749 | } |
4750 | } |
4751 | } |
4752 | return lst; |
4753 | } |
4754 | |
4755 | bool MilestoneItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent ) |
4756 | { |
4757 | //kDebug(planDbg())<<action; |
4758 | if (action == Qt::IgnoreAction) { |
4759 | return true; |
4760 | } |
4761 | if ( !data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { |
4762 | return false; |
4763 | } |
4764 | if ( action == Qt::MoveAction ) { |
4765 | //kDebug(planDbg())<<"MoveAction"; |
4766 | |
4767 | QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); |
4768 | QDataStream stream(&encodedData, QIODevice::ReadOnly); |
4769 | Node *par = 0; |
4770 | if ( parent.isValid() ) { |
4771 | par = node( parent ); |
4772 | } else { |
4773 | par = m_project; |
4774 | } |
4775 | QList<Node*> lst = nodeList( stream ); |
4776 | QList<Node*> nodes = removeChildNodes( lst ); // children goes with their parent |
4777 | foreach ( Node *n, nodes ) { |
4778 | if ( ! m_project->canMoveTask( n, par ) ) { |
4779 | //kDebug(planDbg())<<"Can't move task:"<<n->name(); |
4780 | return false; |
4781 | } |
4782 | } |
4783 | int offset = 0; |
4784 | MacroCommand *cmd = 0; |
4785 | foreach ( Node *n, nodes ) { |
4786 | if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Move tasks" ) ); |
4787 | // append nodes if dropped *on* another node, insert if dropped *after* |
4788 | int pos = row == -1 ? -1 : row + offset; |
4789 | cmd->addCommand( new NodeMoveCmd( m_project, n, par, pos ) ); |
4790 | offset++; |
4791 | } |
4792 | if ( cmd ) { |
4793 | emit executeCommand( cmd ); |
4794 | } |
4795 | //kDebug(planDbg())<<row<<","<<column<<" parent="<<parent.row()<<","<<parent.column()<<":"<<par->name(); |
4796 | return true; |
4797 | } |
4798 | return false; |
4799 | } |
4800 | |
4801 | Node *MilestoneItemModel::node( const QModelIndex &index ) const |
4802 | { |
4803 | Node *n = 0; |
4804 | if ( index.isValid() ) { |
4805 | //kDebug(planDbg())<<index; |
4806 | n = static_cast<Node*>( index.internalPointer() ); |
4807 | } |
4808 | return n; |
4809 | } |
4810 | |
4811 | void MilestoneItemModel::slotNodeChanged( Node *node ) |
4812 | { |
4813 | //kDebug(planDbg())<<node->name(); |
4814 | if ( node == 0 ) { |
4815 | return; |
4816 | } |
4817 | // if ( ! m_nodemap.contains( node->wbsCode() ) || m_nodemap.value( node->wbsCode() ) != node ) { |
4818 | emit layoutAboutToBeChanged(); |
4819 | if ( resetData() ) { |
4820 | reset(); |
4821 | } else { |
4822 | emit layoutChanged(); |
4823 | } |
4824 | return; |
4825 | /* } |
4826 | int row = m_nodemap.values().indexOf( node ); |
4827 | kDebug(planDbg())<<node->name()<<": "<<node->typeToString()<<row; |
4828 | emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount()-1, node ) );*/ |
4829 | } |
4830 | |
4831 | void MilestoneItemModel::slotWbsDefinitionChanged() |
4832 | { |
4833 | //kDebug(planDbg()); |
4834 | if ( m_project == 0 ) { |
4835 | return; |
4836 | } |
4837 | if ( ! m_nodemap.isEmpty() ) { |
4838 | emit layoutAboutToBeChanged(); |
4839 | resetData(); |
4840 | emit layoutChanged(); |
4841 | } |
4842 | } |
4843 | |
4844 | //-------------- |
4845 | NodeSortFilterProxyModel::NodeSortFilterProxyModel( ItemModelBase* model, QObject *parent, bool filterUnscheduled ) |
4846 | : QSortFilterProxyModel( parent ), |
4847 | m_filterUnscheduled( filterUnscheduled ) |
4848 | { |
4849 | setSourceModel( model ); |
4850 | setDynamicSortFilter( true ); |
4851 | } |
4852 | |
4853 | ItemModelBase *NodeSortFilterProxyModel::itemModel() const |
4854 | { |
4855 | return static_cast<ItemModelBase *>( sourceModel() ); |
4856 | } |
4857 | |
4858 | void NodeSortFilterProxyModel::setFilterUnscheduled( bool on ) { |
4859 | m_filterUnscheduled = on; |
4860 | invalidateFilter(); |
4861 | } |
4862 | |
4863 | bool NodeSortFilterProxyModel::filterAcceptsRow ( int row, const QModelIndex & parent ) const |
4864 | { |
4865 | //kDebug(planDbg())<<sourceModel()<<row<<parent; |
4866 | if ( itemModel()->project() == 0 ) { |
4867 | //kDebug(planDbg())<<itemModel()->project(); |
4868 | return false; |
4869 | } |
4870 | if ( m_filterUnscheduled ) { |
4871 | QString s = sourceModel()->data( sourceModel()->index( row, NodeModel::NodeNotScheduled, parent ), Qt::EditRole ).toString(); |
4872 | if ( s == "true" ) { |
4873 | //kDebug(planDbg())<<"Filtered unscheduled:"<<sourceModel()->index( row, 0, parent ); |
4874 | return false; |
4875 | } |
4876 | } |
4877 | bool accepted = QSortFilterProxyModel::filterAcceptsRow( row, parent ); |
4878 | //kDebug(planDbg())<<this<<sourceModel()->index( row, 0, parent )<<"accepted ="<<accepted<<filterRegExp()<<filterRegExp().isEmpty()<<filterRegExp().capturedTexts(); |
4879 | return accepted; |
4880 | } |
4881 | |
4882 | //------------------ |
4883 | TaskModuleModel::TaskModuleModel( QObject *parent ) |
4884 | : QAbstractItemModel( parent ) |
4885 | { |
4886 | } |
4887 | |
4888 | void TaskModuleModel::addTaskModule( Project *project ) |
4889 | { |
4890 | beginInsertRows( QModelIndex(), m_modules.count(), m_modules.count() ); |
4891 | m_modules << project; |
4892 | endInsertRows(); |
4893 | } |
4894 | |
4895 | Qt::ItemFlags TaskModuleModel::flags( const QModelIndex &idx ) const |
4896 | { |
4897 | Qt::ItemFlags f = QAbstractItemModel::flags( idx ) | Qt::ItemIsDropEnabled; |
4898 | if ( idx.isValid() ) { |
4899 | f |= Qt::ItemIsDragEnabled; |
4900 | } |
4901 | return f; |
4902 | } |
4903 | |
4904 | int TaskModuleModel::columnCount (const QModelIndex &/*idx*/ ) const |
4905 | { |
4906 | return 1; |
4907 | } |
4908 | |
4909 | int TaskModuleModel::rowCount( const QModelIndex &idx ) const |
4910 | { |
4911 | return idx.isValid() ? 0 : m_modules.count(); |
4912 | } |
4913 | |
4914 | QVariant TaskModuleModel::data( const QModelIndex& idx, int role ) const |
4915 | { |
4916 | switch ( role ) { |
4917 | case Qt::DisplayRole: return m_modules.value( idx.row() )->name(); |
4918 | case Qt::ToolTipRole: return m_modules.value( idx.row() )->description(); |
4919 | case Qt::WhatsThisRole: return m_modules.value( idx.row() )->description(); |
4920 | default: break; |
4921 | } |
4922 | return QVariant(); |
4923 | } |
4924 | |
4925 | QVariant TaskModuleModel::( int /*section*/, Qt::Orientation orientation , int role ) const |
4926 | { |
4927 | if ( orientation == Qt::Horizontal ) { |
4928 | switch ( role ) { |
4929 | case Qt::DisplayRole: return i18nc( "@title:column" , "Name" ); |
4930 | default: break; |
4931 | } |
4932 | } |
4933 | return QVariant(); |
4934 | } |
4935 | |
4936 | QModelIndex TaskModuleModel::parent( const QModelIndex& /*idx*/ ) const |
4937 | { |
4938 | return QModelIndex(); |
4939 | } |
4940 | |
4941 | QModelIndex TaskModuleModel::index( int row, int column, const QModelIndex &parent ) const |
4942 | { |
4943 | if ( parent.isValid() ) { |
4944 | return QModelIndex(); |
4945 | } |
4946 | return createIndex( row, column, m_modules.value( row ) ); |
4947 | } |
4948 | |
4949 | QStringList TaskModuleModel::mimeTypes() const |
4950 | { |
4951 | return QStringList() << "application/x-vnd.kde.plan" << "text/uri-list" ; |
4952 | } |
4953 | |
4954 | bool TaskModuleModel::dropMimeData( const QMimeData *data, Qt::DropAction /*action*/, int /*row*/, int /*column*/, const QModelIndex &/*parent*/ ) |
4955 | { |
4956 | if ( data->hasUrls() ) { |
4957 | QList<QUrl> urls = data->urls(); |
4958 | kDebug(planDbg())<<urls; |
4959 | foreach ( const QUrl &url, urls ) { |
4960 | KMimeType::Ptr mime = KMimeType::findByUrl( url ); |
4961 | kDebug(planDbg())<<url<<mime->name(); |
4962 | if ( mime->is( "application/x-vnd.kde.plan" ) || mime->is( "application/xml" ) ) { |
4963 | importProject( url ); |
4964 | } |
4965 | } |
4966 | return true; |
4967 | } |
4968 | return false; |
4969 | } |
4970 | |
4971 | bool TaskModuleModel::importProject( const KUrl &url, bool emitsignal ) |
4972 | { |
4973 | if ( ! url.isLocalFile() ) { |
4974 | kDebug(planDbg())<<"TODO: download if url not local" ; |
4975 | return false; |
4976 | } |
4977 | KoStore *store = KoStore::createStore( url.path(), KoStore::Read, "" , KoStore::Auto ); |
4978 | if ( store->bad() ) { |
4979 | // d->lastErrorMessage = i18n( "Not a valid Calligra file: %1", file ); |
4980 | kDebug(planDbg())<<"bad store" <<url.prettyUrl(); |
4981 | delete store; |
4982 | // QApplication::restoreOverrideCursor(); |
4983 | return false; |
4984 | } |
4985 | if ( ! store->open( "root" ) ) { // maindoc.xml |
4986 | kDebug(planDbg())<<"No root" <<url.prettyUrl(); |
4987 | delete store; |
4988 | return false; |
4989 | } |
4990 | KoXmlDocument doc; |
4991 | doc.setContent( store->device() ); |
4992 | KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); |
4993 | Project *project = new Project(); |
4994 | XMLLoaderObject status; |
4995 | status.setVersion( doc.documentElement().attribute( "version" , PLAN_FILE_SYNTAX_VERSION ) ); |
4996 | status.setProject( project ); |
4997 | if ( project->load( element, status ) ) { |
4998 | stripProject( project ); |
4999 | addTaskModule( project ); |
5000 | if ( emitsignal ) { |
5001 | emit saveTaskModule( url, project ); |
5002 | } |
5003 | } else { |
5004 | kDebug(planDbg())<<"Failed to load project from:" <<url; |
5005 | delete project; |
5006 | return false; |
5007 | } |
5008 | return true; |
5009 | } |
5010 | |
5011 | QMimeData* TaskModuleModel::mimeData( const QModelIndexList &lst ) const |
5012 | { |
5013 | QMimeData *mime = new QMimeData(); |
5014 | if ( lst.count() == 1 ) { |
5015 | QModelIndex idx = lst.at( 0 ); |
5016 | if ( idx.isValid() ) { |
5017 | Project *project = m_modules.value( idx.row() ); |
5018 | QDomDocument document( "plan" ); |
5019 | document.appendChild( document.createProcessingInstruction( "xml" , "version=\"1.0\" encoding=\"UTF-8\"" ) ); |
5020 | QDomElement doc = document.createElement( "plan" ); |
5021 | doc.setAttribute( "editor" , "Plan" ); |
5022 | doc.setAttribute( "mime" , "application/x-vnd.kde.plan" ); |
5023 | doc.setAttribute( "version" , PLAN_FILE_SYNTAX_VERSION ); |
5024 | document.appendChild( doc ); |
5025 | project->save( doc ); |
5026 | mime->setData( "application/x-vnd.kde.plan.project" , document.toByteArray() ); |
5027 | } |
5028 | } |
5029 | return mime; |
5030 | } |
5031 | |
5032 | void TaskModuleModel::stripProject( Project *project ) const |
5033 | { |
5034 | foreach ( ScheduleManager *sm, project->scheduleManagers() ) { |
5035 | DeleteScheduleManagerCmd c( *project, sm ); |
5036 | } |
5037 | } |
5038 | |
5039 | void TaskModuleModel::loadTaskModules( const QStringList &files ) |
5040 | { |
5041 | kDebug(planDbg())<<files; |
5042 | foreach ( const QString &file, files ) { |
5043 | importProject( KUrl( file ), false ); |
5044 | } |
5045 | } |
5046 | |
5047 | |
5048 | } //namespace KPlato |
5049 | |
5050 | #include "kptnodeitemmodel.moc" |
5051 | |