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