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