00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kptganttview.h"
00022
00023 #include "kptappointment.h"
00024 #include "kptpart.h"
00025 #include "kptview.h"
00026 #include "kptcanvasitem.h"
00027 #include "kptnode.h"
00028 #include "kptpart.h"
00029 #include "kptproject.h"
00030 #include "kpttask.h"
00031 #include "kptresource.h"
00032 #include "kptdatetime.h"
00033 #include "kpttaskappointmentsview.h"
00034 #include "kptrelation.h"
00035 #include "kptcontext.h"
00036 #include "kptschedule.h"
00037
00038 #include "KDGanttView.h"
00039 #include "KDGanttViewItem.h"
00040 #include "KDGanttViewTaskItem.h"
00041 #include "KDGanttViewSummaryItem.h"
00042 #include "KDGanttViewEventItem.h"
00043
00044 #include <kdebug.h>
00045
00046 #include <q3listview.h>
00047 #include <q3popupmenu.h>
00048
00049 #include <QLineEdit>
00050 #include <QWidget>
00051 #include <QLabel>
00052 #include <QLayout>
00053 #include <QSpinBox>
00054 #include <QSplitter>
00055 #include <QStringList>
00056 #include <QTabWidget>
00057 #include <QPainter>
00058
00059 #include <klocale.h>
00060 #include <kglobal.h>
00061 #include <kprinter.h>
00062 #include <kmessagebox.h>
00063
00064 namespace KPlato
00065 {
00066
00067 class MyKDGanttView : public KDGanttView
00068 {
00069 public:
00070 MyKDGanttView( QWidget *parent, const char *name )
00071 : KDGanttView( parent, name )
00072 {
00073 setAllConnectorsEnabled( false );
00074 setConnectorEnabled( KDGanttViewItem::TaskLinkStart, true );
00075 setConnectorEnabled( KDGanttViewItem::TaskLinkEnd, true );
00076 setAutoScrollEnabled( true );
00077 }
00078
00079
00080
00081 };
00082
00083 GanttView::GanttView( QWidget *parent, bool readWrite, const char* name )
00084 : ViewBase( parent ),
00085 m_readWrite( readWrite ),
00086 m_currentItem( 0 ),
00087 m_taskView( 0 ),
00088 m_firstTime( true ),
00089 m_project( 0 )
00090 {
00091 kDebug() << " ---------------- KPlato: Creating GanttView ----------------" << endl;
00092
00093 QVBoxLayout *l = new QVBoxLayout( this );
00094 l->setMargin( 0 );
00095 m_splitter = new QSplitter( this );
00096 l->addWidget( m_splitter );
00097 m_splitter->setOrientation( Qt::Vertical );
00098
00099 m_gantt = new MyKDGanttView( m_splitter, "Gantt view" );
00100
00101 m_showExpected = true;
00102 m_showOptimistic = false;
00103 m_showPessimistic = false;
00104 m_showResources = false;
00105 m_showTaskName = false;
00106 m_showTaskLinks = false;
00107 m_showProgress = false;
00108 m_showPositiveFloat = false;
00109 m_showCriticalTasks = false;
00110 m_showCriticalPath = false;
00111 m_showNoInformation = false;
00112 m_showAppointments = false;
00113
00114 m_gantt->setHeaderVisible( true );
00115 m_gantt->addColumn( i18nc( "Work Breakdown Structure", "WBS" ) );
00116
00117 KDGanttViewTaskItem *item = new KDGanttViewTaskItem( m_gantt );
00118 Q3ListView *lv = item->listView();
00119 lv->header() ->moveSection( 1, 0 );
00120
00121 m_gantt->setScale( KDGanttView::Day );
00122 m_gantt->setShowLegendButton( false );
00123 m_gantt->setShowHeaderPopupMenu();
00124 m_taskView = new TaskAppointmentsView( m_splitter );
00125
00126
00127
00128
00129
00130 m_taskView->hide();
00131
00132 setReadWriteMode( readWrite );
00133
00134 connect( m_gantt, SIGNAL( lvContextMenuRequested ( KDGanttViewItem *, const QPoint &, int ) ), SLOT ( popupMenuRequested( KDGanttViewItem *, const QPoint &, int ) ) );
00135
00136 connect( m_gantt, SIGNAL( lvCurrentChanged( KDGanttViewItem* ) ), SLOT ( currentItemChanged( KDGanttViewItem* ) ) );
00137
00138 connect( m_gantt, SIGNAL( lvItemDoubleClicked( KDGanttViewItem* ) ), SLOT ( slotItemDoubleClicked( KDGanttViewItem* ) ) );
00139
00140 m_taskLinks.setAutoDelete( true );
00141
00142 if ( m_gantt->firstChild() ) {
00143 m_gantt->firstChild() ->listView() ->setCurrentItem( m_gantt->firstChild() );
00144 m_gantt->firstChild() ->listView() ->setFocus();
00145 }
00146 }
00147
00148 void GanttView::setZoom( double zoom )
00149 {
00150 kDebug() << "setting gantt zoom: " << zoom << endl;
00151
00152 m_taskView->setZoom( zoom );
00153 }
00154
00155 void GanttView::show()
00156 {
00157 m_gantt->show();
00158 }
00159
00160 void GanttView::clear()
00161 {
00162 m_gantt->clear();
00163 m_taskView->clear();
00164 }
00165
00166 void GanttView::setShowTaskLinks( bool on )
00167 {
00168 m_showTaskLinks = on;
00169 m_gantt->setShowTaskLinks( on );
00170 }
00171
00172 void GanttView::draw( Project &project )
00173 {
00174 m_project = &project;
00175
00176 Schedule::Type type = Schedule::Expected;
00177 if ( m_showOptimistic ) {
00178 type = Schedule::Optimistic;
00179 } else if ( m_showPessimistic ) {
00180 type = Schedule::Pessimistic;
00181 }
00182 Schedule *sch = project.findSchedule( type );
00183 if ( sch ) {
00184 project.setCurrentSchedule( sch->id() );
00185 }
00186
00187 m_gantt->setUpdateEnabled( false );
00188
00189 clear();
00190 drawChildren( NULL, project );
00191 drawRelations();
00192
00193 if ( m_firstTime ) {
00194 m_gantt->centerTimelineAfterShow( project.startTime().addDays( -1 ) );
00195 m_firstTime = false;
00196 }
00197 m_gantt->setUpdateEnabled( true );
00198 currentItemChanged( m_currentItem );
00199 }
00200
00201 void GanttView::drawChanges( Project &project )
00202 {
00203 m_project = &project;
00204 drawChanges();
00205 }
00206
00207 void GanttView::drawChanges()
00208 {
00209
00210 Schedule::Type type = Schedule::Expected;
00211 if ( m_showOptimistic ) {
00212 type = Schedule::Optimistic;
00213 } else if ( m_showPessimistic ) {
00214 type = Schedule::Pessimistic;
00215 }
00216 Schedule *sch = m_project->findSchedule( type );
00217 if ( sch ) {
00218 m_project->setCurrentSchedule( sch->id() );
00219 }
00220
00221 m_gantt->setUpdateEnabled( false );
00222 resetDrawn( m_gantt->firstChild() );
00223 updateChildren( m_project );
00224 removeNotDrawn( m_gantt->firstChild() );
00225
00226 m_taskLinks.clear();
00227 drawRelations();
00228
00229 m_gantt->setUpdateEnabled( true );
00230 if ( m_currentItem == 0 && m_gantt->firstChild() ) {
00231 m_gantt->firstChild() ->listView() ->setCurrentItem( m_gantt->firstChild() );
00232 currentItemChanged( m_gantt->firstChild() );
00233 }
00234 currentItemChanged( m_currentItem );
00235 }
00236
00237 void GanttView::drawOnPainter( QPainter* painter, const QRect rect )
00238 {
00239
00240
00241
00242 QSize s = m_gantt->drawContents( 0, false, true );
00243 while ( s.width() < rect.width() ) {
00244 m_gantt->addTicksRight();
00245 m_gantt->setTimelineToEnd();
00246 s = m_gantt->drawContents( 0, false, true );
00247 }
00248 kDebug() << k_funcinfo << rect << " : " << s << endl;
00249 painter->save();
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 m_gantt->drawContents( painter, false, true );
00272
00273
00274
00275
00276 painter->restore();
00277 }
00278
00279 KDGanttViewItem *GanttView::findItem( Node *node )
00280 {
00281 return findItem( node, m_gantt->firstChild() );
00282 }
00283
00284 KDGanttViewItem *GanttView::findItem( Node *node, KDGanttViewItem *item )
00285 {
00286 for ( ; item; item = item->nextSibling() ) {
00287 if ( node == getNode( item ) ) {
00288 return item;
00289 }
00290 KDGanttViewItem *i = findItem( node, item->firstChild() );
00291 if ( i )
00292 return i;
00293 }
00294 return 0;
00295 }
00296
00297 Node *GanttView::getNode( KDGanttViewItem *item ) const
00298 {
00299 if ( item ) {
00300 if ( item->type() == KDGanttViewItem::Event ) {
00301 return static_cast<GanttViewEventItem *>( item ) ->getTask();
00302 } else if ( item->type() == KDGanttViewItem::Task ) {
00303 return static_cast<GanttViewTaskItem *>( item ) ->getTask();
00304 } else if ( item->type() == KDGanttViewItem::Summary ) {
00305 return static_cast<GanttViewSummaryItem *>( item ) ->getNode();
00306 }
00307 }
00308 return 0;
00309 }
00310
00311 bool GanttView::isDrawn( KDGanttViewItem *item )
00312 {
00313 if ( item ) {
00314 if ( item->type() == KDGanttViewItem::Event ) {
00315 return static_cast<GanttViewEventItem *>( item ) ->isDrawn();
00316 } else if ( item->type() == KDGanttViewItem::Task ) {
00317 return static_cast<GanttViewTaskItem *>( item ) ->isDrawn();
00318 } else if ( item->type() == KDGanttViewItem::Summary ) {
00319 return static_cast<GanttViewSummaryItem *>( item ) ->isDrawn();
00320 } else {
00321 kWarning() << k_funcinfo << "Unknown item type: " << item->type() << endl;
00322 }
00323 }
00324 return false;
00325 }
00326
00327 void GanttView::setDrawn( KDGanttViewItem *item, bool state )
00328 {
00329 if ( item ) {
00330 if ( item->type() == KDGanttViewItem::Event ) {
00331 static_cast<GanttViewEventItem *>( item ) ->setDrawn( state );
00332 } else if ( item->type() == KDGanttViewItem::Task ) {
00333 static_cast<GanttViewTaskItem *>( item ) ->setDrawn( state );
00334 } else if ( item->type() == KDGanttViewItem::Summary ) {
00335 static_cast<GanttViewSummaryItem *>( item ) ->setDrawn( state );
00336 } else {
00337 kWarning() << k_funcinfo << "Unknown item type: " << item->type() << endl;
00338 }
00339 }
00340 return ;
00341 }
00342
00343 void GanttView::resetDrawn( KDGanttViewItem *_item )
00344 {
00345 KDGanttViewItem * nextItem, *item = _item;
00346 for ( ; item; item = nextItem ) {
00347 nextItem = item->nextSibling();
00348 setDrawn( item, false );
00349 resetDrawn( item->firstChild() );
00350 }
00351 }
00352
00353 void GanttView::removeNotDrawn( KDGanttViewItem *_item )
00354 {
00355 KDGanttViewItem * nextItem, *item = _item;
00356 for ( ; item; item = nextItem ) {
00357 nextItem = item->nextSibling();
00358 if ( !isDrawn( item ) ) {
00359 if ( item == m_currentItem )
00360 m_currentItem = 0;
00361 deleteItem( item );
00362 } else {
00363 removeNotDrawn( item->firstChild() );
00364 }
00365 }
00366 }
00367
00368 void GanttView::deleteItem( KDGanttViewItem *item )
00369 {
00370
00371 if ( item->parent() )
00372 item->parent() ->takeItem( item );
00373 else
00374 item->listView() ->takeItem( item );
00375 delete item;
00376 }
00377
00378 KDGanttViewItem *GanttView::correctType( KDGanttViewItem *item, Node *node )
00379 {
00380
00381 switch ( node->type() ) {
00382 case Node::Type_Project:
00383 return item;
00384 break;
00385 case Node::Type_Summarytask:
00386 case Node::Type_Subproject:
00387 if ( item->type() == KDGanttViewItem::Summary )
00388 return item;
00389 break;
00390 case Node::Type_Task:
00391 if ( item->type() == KDGanttViewItem::Task )
00392 return item;
00393 break;
00394 case Node::Type_Milestone:
00395 if ( item->type() == KDGanttViewItem::Event )
00396 return item;
00397 break;
00398 default:
00399 return item;
00400 break;
00401 }
00402 KDGanttViewItem *newItem = addNode( item->parent(), node, item );
00403 newItem->setOpen( item->isOpen() );
00404 deleteItem( item );
00405 return newItem;
00406 }
00407
00408 void GanttView::correctPosition( KDGanttViewItem *item, Node *node )
00409 {
00410 KDGanttViewItem * after = findItem( node->siblingBefore() );
00411 if ( after ) {
00412 item->moveItem( after );
00413 }
00414 }
00415
00416 KDGanttViewItem *GanttView::correctParent( KDGanttViewItem *item, Node *node )
00417 {
00418 KDGanttViewItem * p = findItem( node->getParent() );
00419 if ( p == item->parent() ) {
00420 return item;
00421 }
00422 KDGanttViewItem *newItem = addNode( p, node );
00423 newItem->setOpen( item->isOpen() );
00424 deleteItem( item );
00425 return newItem;
00426 }
00427
00428 void GanttView::updateChildren( Node *parentNode )
00429 {
00430
00431 foreach ( Node * n, parentNode->childNodeIterator() ) {
00432 updateNode( n );
00433 }
00434 }
00435
00436 void GanttView::updateNode( Node *node )
00437 {
00438
00439 KDGanttViewItem * item = findItem( node );
00440 if ( !item ) {
00441 item = addNode( findItem( node->getParent() ), node, findItem( node->siblingBefore() ) );
00442 if ( item && node->type() == Node::Type_Summarytask )
00443 updateChildren( node );
00444 return ;
00445 }
00446 item = correctType( item, node );
00447 item = correctParent( item, node );
00448 correctPosition( item, node );
00449
00450 modifyNode( node );
00451
00452 if ( node->type() == Node::Type_Summarytask )
00453 updateChildren( node );
00454 }
00455
00456 void GanttView::modifyChildren( Node *node )
00457 {
00458
00459 foreach ( Node * n, node->childNodeIterator() ) {
00460 modifyNode( n );
00461 modifyChildren( n );
00462 }
00463 }
00464
00465 void GanttView::modifyNode( Node *node )
00466 {
00467
00468 KDGanttViewItem * item = findItem( node );
00469 if ( !item ) {
00470 kDebug() << k_funcinfo << " Item not found" << endl;
00471 return ;
00472 }
00473 if ( node->type() == Node::Type_Project ) {
00474 return modifyProject( item, node );
00475 }
00476 if ( node->type() == Node::Type_Subproject ) {
00477 return modifyProject( item, node );
00478 }
00479 if ( node->type() == Node::Type_Summarytask ) {
00480 return modifySummaryTask( item, static_cast<Task *>( node ) );
00481 }
00482 if ( node->type() == Node::Type_Task ) {
00483 return modifyTask( item, static_cast<Task *>( node ) );
00484 }
00485 if ( node->type() == Node::Type_Milestone ) {
00486 return modifyMilestone( item, static_cast<Task *>( node ) );
00487 }
00488 return ;
00489 }
00490
00491 void GanttView::modifyProject( KDGanttViewItem *item, Node *node )
00492 {
00493
00494 item->setListViewText( node->name() );
00495 item->setListViewText( 1, node->wbs() );
00496 item->setStartTime( node->startTime() );
00497 item->setEndTime( node->endTime() );
00498
00499 setDrawn( item, true );
00500
00501 }
00502
00503 void GanttView::modifySummaryTask( KDGanttViewItem *item, Task *task )
00504 {
00505
00506 KLocale * locale = KGlobal::locale();
00507
00508 if ( task->currentSchedule() == 0 ) {
00509 item->setShowNoInformation( m_showNoInformation );
00510 item->setStartTime( task->projectNode() ->startTime() );
00511 item->setEndTime( item->startTime().addDays( 1 ) );
00512 } else {
00513 bool noinf = m_showNoInformation && ( task->notScheduled() || ( m_project ? m_project->notScheduled() : false ) );
00514 item->setShowNoInformation( noinf );
00515 item->setStartTime( task->startTime() );
00516 item->setEndTime( task->endTime() );
00517 }
00518 item->setListViewText( task->name() );
00519 item->setListViewText( 1, task->wbs() );
00520
00521 if ( m_showTaskName ) {
00522 item->setText( task->name() );
00523 } else {
00524 item->setText( QString() );
00525 }
00526 QString w = i18n( "Name: %1", task->name() );
00527 if ( !task->notScheduled() ) {
00528 w += "\n" + i18n( "Start: %1", locale->formatDateTime( task->startTime() ) );
00529 w += "\n" + i18n( "End: %1", locale->formatDateTime( task->endTime() ) );
00530 }
00531 bool ok = true;
00532 if ( task->notScheduled() ) {
00533 w += "\n" + i18n( "Not scheduled" );
00534 ok = false;
00535 } else {
00536 if ( !m_showNoInformation && m_project && m_project->notScheduled() ) {
00537 ok = false;
00538 }
00539 }
00540 if ( ok ) {
00541 QColor c( Qt::cyan );
00542 item->setColors( c, c, c );
00543 } else {
00544 QColor c( Qt::yellow );
00545 item->setColors( c, c, c );
00546 }
00547 item->setTooltipText( w );
00548 setDrawn( item, true );
00549 }
00550
00551 void GanttView::modifyTask( KDGanttViewItem *item, Task *task )
00552 {
00553
00554 KLocale * locale = KGlobal::locale();
00555
00556 item->setListViewText( task->name() );
00557 item->setListViewText( 1, task->wbs() );
00558 if ( task->currentSchedule() == 0 ) {
00559 item->setShowNoInformation( m_showNoInformation );
00560 item->setStartTime( task->projectNode() ->startTime() );
00561 item->setEndTime( item->startTime().addDays( 1 ) );
00562 } else {
00563 bool noinf = m_showNoInformation && ( task->notScheduled() || ( m_project ? m_project->notScheduled() : false ) );
00564 item->setShowNoInformation( noinf );
00565 item->setStartTime( task->startTime() );
00566 item->setEndTime( task->endTime() );
00567 }
00568
00569 QString text;
00570 if ( m_showTaskName ) {
00571 text = task->name();
00572 }
00573 if ( m_showResources && !task->notScheduled() ) {
00574 QList<Appointment*> lst = task->appointments();
00575 if ( lst.count() > 0 ) {
00576 if ( !text.isEmpty() )
00577 text += ' ';
00578 text += '(';
00579 bool first = true;
00580 foreach ( Appointment * a, lst ) {
00581 if ( !first )
00582 text += ", ";
00583 text += a->resource() ->resource() ->name();
00584 first = false;
00585 }
00586 text += ')';
00587 }
00588 }
00589 item->setText( text );
00590 if ( m_showProgress ) {
00591 item->setProgress( task->progress().percentFinished );
00592 } else {
00593 item->setProgress( 0 );
00594 }
00595 if ( m_showPositiveFloat ) {
00596 QDateTime t = task->endTime() + task->positiveFloat();
00597 if ( t.isValid() && t > task->endTime() ) {
00598 item->setFloatEndTime( t );
00599 } else {
00600 item->setFloatEndTime( QDateTime() );
00601 }
00602 } else {
00603 item->setFloatStartTime( QDateTime() );
00604 item->setFloatEndTime( QDateTime() );
00605 }
00606 QString w = i18n( "Name: %1", task->name() );
00607 if ( !task->notScheduled() ) {
00608 w += "\n";
00609 w += i18n( "Start: %1", locale->formatDateTime( task->startTime() ) );
00610 w += "\n";
00611 w += i18n( "End: %1", locale->formatDateTime( task->endTime() ) );
00612 if ( m_showProgress ) {
00613 w += "\n";
00614 w += i18n( "Completion: %1%", task->progress().percentFinished );
00615 }
00616 if ( task->positiveFloat() > Duration::zeroDuration ) {
00617 w += "\n" + i18n( "Float: %1", task->positiveFloat().toString( Duration::Format_i18nDayTime ) );
00618 }
00619 if ( task->inCriticalPath() ) {
00620 w += "\n" + i18n( "Critical path" );
00621 } else if ( task->isCritical() ) {
00622 w += "\n" + i18n( "Critical" );
00623 }
00624 }
00625 QString sts;
00626 bool ok = true;
00627 if ( task->notScheduled() ) {
00628 sts += "\n" + i18n( "Not scheduled" );
00629 ok = false;
00630 } else {
00631 if ( task->resourceError() ) {
00632 sts += "\n" + i18n( "No resource assigned" );
00633 ok = false;
00634 }
00635 if ( task->resourceNotAvailable() ) {
00636 sts += "\n" + i18n( "Resource not available" );
00637 ok = false;
00638 }
00639 if ( task->schedulingError() ) {
00640 sts += "\n" + i18n( "Scheduling conflict" );
00641 ok = false;
00642 }
00643 if ( task->effortMetError() ) {
00644 sts += "\n" + i18n( "Requested effort could not be met" );
00645 ok = false;
00646 }
00647 if ( task->resourceOverbooked() ) {
00648 ok = false;
00649 QStringList rl = task->overbookedResources();
00650 sts += "\n" + i18nc( "arg: list of resources", "Resource overbooked: %1" ).arg( rl.join( "," ) );
00651
00652 }
00653 if ( !m_showNoInformation && m_project && m_project->notScheduled() ) {
00654 ok = false;
00655 }
00656 }
00657 if ( ok ) {
00658 QColor c( Qt::green );
00659 item->setColors( c, c, c );
00660 } else {
00661 w += sts;
00662 QColor c( Qt::yellow );
00663 item->setColors( c, c, c );
00664 }
00665 item->setHighlight( false );
00666 if ( m_showCriticalTasks ) {
00667 item->setHighlight( task->isCritical() );
00668 } else if ( m_showCriticalPath ) {
00669 item->setHighlight( task->inCriticalPath() );
00670 }
00671
00672 item->setTooltipText( w );
00673 setDrawn( item, true );
00674 }
00675
00676 void GanttView::modifyMilestone( KDGanttViewItem *item, Task *task )
00677 {
00678
00679 KLocale * locale = KGlobal::locale();
00680
00681 if ( task->currentSchedule() == 0 ) {
00682 item->setShowNoInformation( m_showNoInformation );
00683 item->setStartTime( task->projectNode() ->startTime() );
00684 } else {
00685 bool noinf = m_showNoInformation && ( task->notScheduled() || ( m_project ? m_project->notScheduled() : false ) );
00686 item->setShowNoInformation( noinf );
00687 item->setStartTime( task->startTime() );
00688 }
00689 item->setListViewText( task->name() );
00690 item->setListViewText( 1, task->wbs() );
00691
00692 if ( m_showTaskName ) {
00693 item->setText( task->name() );
00694 } else {
00695 item->setText( QString() );
00696 }
00697 if ( m_showPositiveFloat ) {
00698 DateTime t = task->startTime() + task->positiveFloat();
00699
00700 if ( t.isValid() && t > task->startTime() ) {
00701 item->setFloatEndTime( t );
00702 } else {
00703 item->setFloatEndTime( QDateTime() );
00704 }
00705 } else {
00706 item->setFloatStartTime( QDateTime() );
00707 item->setFloatEndTime( QDateTime() );
00708 }
00709
00710
00711 QString w = i18n( "Name: %1", task->name() );
00712 if ( !task->notScheduled() ) {
00713 w += "\n" + i18n( "Time: %1", locale->formatDateTime( task->startTime() ) );
00714
00715 if ( task->positiveFloat() > Duration::zeroDuration ) {
00716 w += "\n" + i18n( "Float: %1", task->positiveFloat().toString( Duration::Format_i18nDayTime ) );
00717 }
00718 if ( task->inCriticalPath() ) {
00719 w += "\n" + i18n( "Critical path" );
00720 } else if ( task->isCritical() ) {
00721 w += "\n" + i18n( "Critical" );
00722 }
00723 }
00724 bool ok = true;
00725 if ( task->notScheduled() ) {
00726 w += "\n" + i18n( "Not scheduled" );
00727 ok = false;
00728 } else {
00729 if ( task->schedulingError() ) {
00730 w += "\n" + i18n( "Scheduling conflict" );
00731 ok = false;
00732 }
00733 if ( !m_showNoInformation && m_project && m_project->notScheduled() ) {
00734 ok = false;
00735 }
00736 }
00737 if ( ok ) {
00738 QColor c( Qt::blue );
00739 item->setColors( c, c, c );
00740 } else {
00741 QColor c( Qt::yellow );
00742 item->setColors( c, c, c );
00743 }
00744 item->setHighlight( false );
00745 if ( m_showCriticalTasks ) {
00746 item->setHighlight( task->isCritical() );
00747 } else if ( m_showCriticalPath ) {
00748 item->setHighlight( task->inCriticalPath() );
00749 }
00750
00751 item->setTooltipText( w );
00752 setDrawn( item, true );
00753 }
00754
00755 KDGanttViewItem *GanttView::addNode( KDGanttViewItem *parentItem, Node *node, KDGanttViewItem *after )
00756 {
00757
00758 if ( node->type() == Node::Type_Project ) {
00759 return addProject( parentItem, node, after );
00760 }
00761 if ( node->type() == Node::Type_Subproject ) {
00762 return addSubProject( parentItem, node, after );
00763 }
00764 if ( node->type() == Node::Type_Summarytask ) {
00765 return addSummaryTask( parentItem, static_cast<Task *>( node ), after );
00766 }
00767 if ( node->type() == Node::Type_Task ) {
00768 return addTask( parentItem, static_cast<Task *>( node ), after );
00769 }
00770 if ( node->type() == Node::Type_Milestone ) {
00771 return addMilestone( parentItem, static_cast<Task *>( node ), after );
00772 }
00773 return 0;
00774 }
00775
00776 KDGanttViewItem *GanttView::addProject( KDGanttViewItem *parentItem, Node *node, KDGanttViewItem *after )
00777 {
00778
00779 GanttViewSummaryItem * item;
00780 if ( parentItem ) {
00781 item = new GanttViewSummaryItem( parentItem, node );
00782 } else {
00783
00784 item = new GanttViewSummaryItem( m_gantt, node );
00785 }
00786 if ( after )
00787 item->moveItem( after );
00788 modifyProject( item, node );
00789 return item;
00790 }
00791
00792 KDGanttViewItem *GanttView::addSubProject( KDGanttViewItem *parentItem, Node *node, KDGanttViewItem *after )
00793 {
00794
00795 return addProject( parentItem, node, after );
00796 }
00797
00798 KDGanttViewItem *GanttView::addSummaryTask( KDGanttViewItem *parentItem, Task *task, KDGanttViewItem *after )
00799 {
00800
00801
00802 GanttViewSummaryItem * item;
00803 if ( parentItem ) {
00804 item = new GanttViewSummaryItem( parentItem, task );
00805 } else {
00806
00807 item = new GanttViewSummaryItem( m_gantt, task );
00808 }
00809 if ( after )
00810 item->moveItem( after );
00811 modifySummaryTask( item, task );
00812 return item;
00813 }
00814
00815 KDGanttViewItem *GanttView::addTask( KDGanttViewItem *parentItem, Task *task, KDGanttViewItem *after )
00816 {
00817
00818
00819 GanttViewTaskItem * item;
00820 if ( parentItem ) {
00821 item = new GanttViewTaskItem( parentItem, task );
00822 } else {
00823
00824 item = new GanttViewTaskItem( m_gantt, task );
00825 }
00826 if ( after )
00827 item->moveItem( after );
00828 modifyTask( item, task );
00829 return item;
00830 }
00831
00832 KDGanttViewItem *GanttView::addMilestone( KDGanttViewItem *parentItem, Task *task, KDGanttViewItem *after )
00833 {
00834
00835 GanttViewEventItem * item;
00836 if ( parentItem ) {
00837 item = new GanttViewEventItem( parentItem, task );
00838 } else {
00839
00840 item = new GanttViewEventItem( m_gantt, task );
00841 }
00842 if ( after )
00843 item->moveItem( after );
00844 modifyMilestone( item, task );
00845 return item;
00846 }
00847
00848 void GanttView::drawChildren( KDGanttViewItem *parentItem, Node &parentNode )
00849 {
00850
00851 foreach ( Node * n, parentNode.childNodeIterator() ) {
00852 if ( n->type() == Node::Type_Project )
00853 drawProject( parentItem, n );
00854 else if ( n->type() == Node::Type_Subproject )
00855 drawSubProject( parentItem, n );
00856 else if ( n->type() == Node::Type_Summarytask ) {
00857 Task * t = dynamic_cast<Task *>( n );
00858 Q_ASSERT( t );
00859 drawSummaryTask( parentItem, t );
00860 } else if ( n->type() == Node::Type_Task ) {
00861 Task * t = dynamic_cast<Task *>( n );
00862 Q_ASSERT( t );
00863 drawTask( parentItem, t );
00864 } else if ( n->type() == Node::Type_Milestone ) {
00865 Task * t = dynamic_cast<Task *>( n );
00866 Q_ASSERT( t );
00867 drawMilestone( parentItem, t );
00868 } else
00869 kDebug() << k_funcinfo << "Node type " << n->type() << " not implemented yet" << endl;
00870
00871 }
00872 }
00873
00874
00875 void GanttView::drawProject( KDGanttViewItem *parentItem, Node *node )
00876 {
00877
00878 GanttViewSummaryItem * item = dynamic_cast<GanttViewSummaryItem*>( addProject( parentItem, node ) );
00879 drawChildren( item, *node );
00880 }
00881
00882 void GanttView::drawSubProject( KDGanttViewItem *parentItem, Node *node )
00883 {
00884
00885 GanttViewSummaryItem * item = dynamic_cast<GanttViewSummaryItem*>( addSubProject( parentItem, node ) );
00886 drawChildren( item, *node );
00887 }
00888
00889 void GanttView::drawSummaryTask( KDGanttViewItem *parentItem, Task *task )
00890 {
00891
00892 GanttViewSummaryItem * item = dynamic_cast<GanttViewSummaryItem*>( addSummaryTask( parentItem, task ) );
00893 drawChildren( item, *task );
00894 }
00895
00896 void GanttView::drawTask( KDGanttViewItem *parentItem, Task *task )
00897 {
00898
00899 addTask( parentItem, task );
00900 }
00901
00902 void GanttView::drawMilestone( KDGanttViewItem *parentItem, Task *task )
00903 {
00904
00905 addMilestone( parentItem, task );
00906 }
00907
00908 void GanttView::addTaskLink( KDGanttViewTaskLink *link )
00909 {
00910
00911 m_taskLinks.append( link );
00912 }
00913
00914 void GanttView::drawRelations()
00915 {
00916 if ( !m_showTaskLinks )
00917 return ;
00918 KDGanttViewItem *item = m_gantt->firstChild();
00919
00920 for ( ; item; item = item->nextSibling() ) {
00921 drawRelations( item );
00922 drawChildRelations( item->firstChild() );
00923 }
00924 }
00925
00926 void GanttView::drawChildRelations( KDGanttViewItem *item )
00927 {
00928
00929 for ( ; item; item = item->nextSibling() ) {
00930 drawRelations( item );
00931 drawChildRelations( item->firstChild() );
00932 }
00933 }
00934
00935 void GanttView::drawRelations( KDGanttViewItem *item )
00936 {
00937
00938 if ( !item )
00939 return ;
00940
00941 GanttViewSummaryItem *summaryItem = dynamic_cast<GanttViewSummaryItem *>( item );
00942 if ( summaryItem ) {
00943
00944 summaryItem->insertRelations( this );
00945 return ;
00946 }
00947 GanttViewTaskItem *taskItem = dynamic_cast<GanttViewTaskItem *>( item );
00948 if ( taskItem ) {
00949
00950 taskItem->insertRelations( this );
00951 return ;
00952 }
00953 GanttViewEventItem *milestoneItem = dynamic_cast<GanttViewEventItem *>( item );
00954 if ( milestoneItem ) {
00955
00956 milestoneItem->insertRelations( this );
00957 return ;
00958 }
00959 kDebug() << k_funcinfo << "Unknown item type: " << item->listViewText() << endl;
00960 }
00961
00962 void GanttView::currentItemChanged( KDGanttViewItem* item )
00963 {
00964
00965 m_taskView->clear();
00966 m_gantt->setSelected( m_currentItem, false );
00967 m_currentItem = item;
00968 if ( item ) {
00969 m_gantt->setSelected( item, true );
00970 if ( m_showAppointments ) {
00971 m_taskView->show();
00972 GanttViewTaskItem *taskItem = dynamic_cast<GanttViewTaskItem *>( item );
00973 if ( taskItem ) {
00974 m_taskView->draw( taskItem->getTask() );
00975 } else {
00976 GanttViewEventItem *msItem = dynamic_cast<GanttViewEventItem *>( item );
00977 if ( msItem )
00978 m_taskView->draw( msItem->getTask() );
00979 }
00980 } else {
00981 m_taskView->hide();
00982 }
00983 }
00984 emit enableActions( true );
00985 }
00986
00987 Node *GanttView::currentNode() const
00988 {
00989 return getNode( m_currentItem );
00990 }
00991
00992 void GanttView::popupMenuRequested( KDGanttViewItem * item, const QPoint & pos, int )
00993 {
00994
00995 if ( item == 0 ) {
00996 kDebug() << "No item selected" << endl;
00997 return ;
00998 }
00999 Node *n = getNode( item );
01000 if ( n == 0 ) {
01001 kDebug() << "No node selected" << endl;
01002 return ;
01003 }
01004 Task *t = dynamic_cast<Task*>( n );
01005 if ( t && ( t->type() == Node::Type_Task || t->type() == Node::Type_Milestone ) ) {
01006 emit requestPopupMenu( "task_popup", pos );
01007
01008
01009
01010
01011
01012
01013 return ;
01014 }
01015 if ( t && t->type() == Node::Type_Summarytask ) {
01016 emit requestPopupMenu( "summarytask_popup", pos );
01017
01018
01019
01020
01021
01022
01023 return ;
01024 }
01025
01026 }
01027
01028 void GanttView::slotItemDoubleClicked( KDGanttViewItem* item )
01029 {
01030
01031 emit itemDoubleClicked();
01032 }
01033
01034
01035
01036 void GanttView::print( KPrinter &prt )
01037 {
01038
01039
01040 KDGanttViewItem * selItem = m_gantt->selectedItem();
01041 if ( selItem )
01042 selItem->setSelected( false );
01043
01044
01045
01046
01047
01048
01049 uint top, left, bottom, right;
01050 prt.margins( &top, &left, &bottom, &right );
01051
01052
01053
01054
01055
01056 QSize size = m_gantt->drawContents( 0 );
01057
01058 QPainter p;
01059 p.begin( &prt );
01060 p.setViewport( left, top, prt.width() - left - right, prt.height() - top - bottom );
01061 p.setClipRect( left, top, prt.width() - left - right, prt.height() - top - bottom );
01062
01063
01064 p.drawRect( 0, 0, prt.width(), prt.height() );
01065 QString text;
01066 int hei = 0;
01067 text = KGlobal::locale() ->formatDateTime( QDateTime::currentDateTime() );
01068 QRect r = p.boundingRect( prt.width() - 1, 0, 0, 0, Qt::AlignRight, text );
01069 p.drawText( r, Qt::AlignRight, text );
01070 hei = r.height();
01071
01072 if ( m_project ) {
01073 QRect re = p.boundingRect( 1, 0, 0, 0, Qt::AlignLeft, text );
01074 re.setWidth( prt.width() - r.width() - 5 );
01075 p.drawText( re, Qt::AlignLeft, m_project->name() );
01076 hei = r.height();
01077
01078 hei = qMax( hei, re.height() );
01079 }
01080
01081 hei++;
01082 p.drawLine( 0, hei, prt.width(), hei );
01083 hei += 3;
01084
01085 float dx = ( float ) ( prt.width() - 2 ) / ( float ) size.width();
01086 float dy = ( float ) ( prt.height() - hei ) / ( float ) size.height();
01087 float scale;
01088
01089 if ( dx < dy )
01090 scale = dx;
01091 else
01092 scale = dy;
01093
01094 p.translate( 1, hei );
01095 p.scale( scale, scale );
01096 m_gantt->drawContents( &p );
01097
01098
01099
01100
01101
01102
01103 p.end();
01104 if ( selItem )
01105 selItem->setSelected( true );
01106 }
01107
01108 void GanttView::slotItemRenamed( KDGanttViewItem* item, int col, const QString& str )
01109 {
01110
01111 if ( col == 0 ) {
01112 emit itemRenamed( getNode( item ), str );
01113 }
01114 }
01115
01116 void GanttView::slotGvItemClicked( KDGanttViewItem * )
01117 {}
01118
01119
01120 bool GanttView::exportGantt( QIODevice* device )
01121 {
01122 kDebug() << k_funcinfo << endl;
01123 return m_gantt->saveProject( device );
01124 }
01125
01126 void GanttView::slotCreateTaskLink( KDGanttViewItem* from, KDGanttViewItem::Connector fc, KDGanttViewItem* to, KDGanttViewItem::Connector tc )
01127 {
01128 kDebug() << k_funcinfo << ( from ? from->listViewText() : "null" ) << " fc=" << fc << " to " << ( to ? to->listViewText() : "null" ) << " tc=" << tc << endl;
01129 Node *par = getNode( from );
01130 Node *child = getNode( to );
01131 if ( !par || !child || !( par->legalToLink( child ) ) ) {
01132 KMessageBox::sorry( this, i18n( "Cannot link these nodes" ) );
01133 return ;
01134 }
01135 int rt = linkTypeToRelation( fc, tc );
01136 if ( rt == Relation::None ) {
01137 KMessageBox::sorry( this, i18n( "Cannot link these nodes" ) );
01138 return ;
01139 }
01140 Relation *rel = child->findRelation( par );
01141 if ( rel )
01142 emit modifyRelation( rel, rt );
01143 else
01144 emit addRelation( par, child, rt );
01145
01146 return ;
01147 }
01148
01149 int GanttView::linkTypeToRelation( KDGanttViewItem::Connector fc, KDGanttViewItem::Connector tc )
01150 {
01151 if ( fc == KDGanttViewItem::TaskLinkStart ) {
01152
01153
01154 return Relation::StartStart;
01155
01156
01157
01158
01159
01160
01161 } else if ( fc == KDGanttViewItem::TaskLinkEnd ) {
01162 if ( tc == KDGanttViewItem::TaskLinkStart ) {
01163 return Relation::FinishStart;
01164 }
01165 if ( tc == KDGanttViewItem::TaskLinkEnd ) {
01166 return Relation::FinishFinish;
01167 }
01168 }
01169 return Relation::None;
01170 }
01171
01172 void GanttView::slotModifyLink( KDGanttViewTaskLink* link )
01173 {
01174
01175
01176 Node * par = getNode( link->from().first() );
01177 Relation *rel = par->findRelation( getNode( link->to().first() ) );
01178 if ( rel )
01179 emit modifyRelation( rel );
01180 }
01181
01182 bool GanttView::setContext( Context::Ganttview &context, Project& )
01183 {
01184
01185
01186 Q3ValueList<int> list = m_splitter->sizes();
01187 list[ 0 ] = context.ganttviewsize;
01188 list[ 1 ] = context.taskviewsize;
01189 m_splitter->setSizes( list );
01190
01191
01192
01193
01194 m_showResources = context.showResources ;
01195 m_showTaskName = context.showTaskName;
01196 m_showTaskLinks = context.showTaskLinks;
01197 m_showProgress = context.showProgress;
01198 m_showPositiveFloat = context.showPositiveFloat;
01199 m_showCriticalTasks = context.showCriticalTasks;
01200 m_showCriticalPath = context.showCriticalPath;
01201 m_showNoInformation = context.showNoInformation;
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 return true;
01212 }
01213
01214 void GanttView::getContext( Context::Ganttview &context ) const
01215 {
01216
01217 context.ganttviewsize = m_splitter->sizes() [ 0 ];
01218 context.taskviewsize = m_splitter->sizes() [ 1 ];
01219
01220 if ( currentNode() ) {
01221 context.currentNode = currentNode() ->id();
01222 }
01223 context.showResources = m_showResources;
01224 context.showTaskName = m_showTaskName;
01225 context.showTaskLinks = m_showTaskLinks;
01226 context.showProgress = m_showProgress;
01227 context.showPositiveFloat = m_showPositiveFloat;
01228 context.showCriticalTasks = m_showCriticalTasks;
01229 context.showCriticalPath = m_showCriticalPath;
01230 context.showNoInformation = m_showNoInformation;
01231 getContextClosedNodes( context, m_gantt->firstChild() );
01232 }
01233
01234 void GanttView::getContextClosedNodes( Context::Ganttview &context, KDGanttViewItem *item ) const
01235 {
01236 if ( item == 0 )
01237 return ;
01238 for ( KDGanttViewItem * i = item; i; i = i->nextSibling() ) {
01239 if ( !i->isOpen() ) {
01240 context.closedNodes.append( getNode( i ) ->id() );
01241
01242 }
01243 getContextClosedNodes( context, i->firstChild() );
01244 }
01245 }
01246
01247 void GanttView::setReadWriteMode( bool on )
01248 {
01249 m_readWrite = on;
01250 disconnect( m_gantt, SIGNAL( gvCreateTaskLink( KDGanttViewItem*, KDGanttViewItem::Connector, KDGanttViewItem*, KDGanttViewItem::Connector ) ), this, SLOT( slotCreateTaskLink( KDGanttViewItem*, KDGanttViewItem::Connector, KDGanttViewItem*, KDGanttViewItem::Connector ) ) );
01251 disconnect( m_gantt, SIGNAL( taskLinkDoubleClicked( KDGanttViewTaskLink* ) ), this, SLOT( slotModifyLink( KDGanttViewTaskLink* ) ) );
01252
01253 if ( on ) {
01254 connect( m_gantt, SIGNAL( gvCreateTaskLink( KDGanttViewItem*, KDGanttViewItem::Connector, KDGanttViewItem*, KDGanttViewItem::Connector ) ), this, SLOT( slotCreateTaskLink( KDGanttViewItem*, KDGanttViewItem::Connector, KDGanttViewItem*, KDGanttViewItem::Connector ) ) );
01255
01256 connect( m_gantt, SIGNAL( taskLinkDoubleClicked( KDGanttViewTaskLink* ) ), SLOT( slotModifyLink( KDGanttViewTaskLink* ) ) );
01257 }
01258 setRenameEnabled( m_gantt->firstChild(), on );
01259 }
01260
01261 void GanttView::setRenameEnabled( Q3ListViewItem *item, bool on )
01262 {
01263 if ( item == 0 )
01264 return ;
01265 for ( Q3ListViewItem * i = item; i; i = i->nextSibling() ) {
01266 i->setRenameEnabled( 0, on );
01267 setRenameEnabled( i->firstChild(), on );
01268 }
01269 }
01270
01271 }
01272
01273 #include "kptganttview.moc"