/* This file is part of the KDE project Copyright (C) 2003 - 2004 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpttask.h" #include "kptcanvasitem.h" #include "kptrelation.h" #include "kptpertcanvas.h" #include "kptganttview.h" #include #include #include #include #include #include namespace KPlato { PertNodeItem::PertNodeItem( PertCanvas *view, Node &node, int row, int col ) : QCanvasPolygon(view->canvas()), m_node(node), m_row(row), m_col(col) { m_x = m_y = 0; m_wgap = view->verticalGap(); m_hgap = view->horizontalGap(); m_width = view->itemSize().width(); m_height = view->itemSize().height(); m_name = new QCanvasText(node.name(), view->canvas()); m_childRelations.setAutoDelete(true); } PertNodeItem::~PertNodeItem() { QCanvasItemList list = canvas()->allItems(); QCanvasItemList::Iterator it = list.begin(); for (; it != list.end(); ++it) { if ( *it == m_name ) m_name->hide(); if ( *it == m_leader ) m_leader->hide(); } hide(); } int PertNodeItem::rtti() const { return RTTI; } int PertNodeItem::RTTI = 2000; void PertNodeItem::setVisible(bool yes) { //kdDebug()<allItems(); QCanvasItemList::Iterator it = list.begin(); for (; it != list.end(); ++it) { if ( *it == m_name ) m_name->setVisible(yes); if ( *it == m_leader ) m_leader->setVisible(yes); } } void PertNodeItem::move(PertCanvas *view, int row, int col) { //kdDebug()<mapNode(this); // Now map my children QPtrListIterator it(m_childRelations); for (; it.current(); ++it) { view->mapChildNode(this, it.current()->childItem, it.current()->relation->type()); } // now move the item on the canvas m_x = x(col); m_y = y(row); m_left = QPoint(m_x, m_y + m_height/2); m_right = QPoint(m_x + m_width, m_y + m_height/2); QCanvasPolygon::move(m_x, m_y); if (m_name) m_name->move(m_x+5, m_y+2); setVisible(true); //kdDebug()<canvas()), m_view(view), m_rel(rel), m_parentItem(parent), m_childItem(child) { //kdDebug()<node().name()<<" Child="<node().name()< parent column // b) Relation::FinishFinish: child column >= parent column // c) Relation::StartStart: child column >= parent column // d) Child row can be >= parent row wgap = m_view->verticalGap(); hgap = m_view->horizontalGap(); // could not use ...rect() here, don't know why parentTop = (int)(m_parentItem->y()); parentBottom = parentTop + (int)(m_parentItem->height()); childTop = (int)(m_childItem->y()); childRow = m_childItem->row(); childCol = m_childItem->column(); parentRow = m_parentItem->row(); parentCol = m_parentItem->column(); //kdDebug()<node().name()<<" ("<parent()->name()<<" to child: "<child()->name()<exitPoint(Relation::FinishStart); QPoint childPoint = m_childItem->entryPoint(Relation::FinishStart); QPointArray a; a.putPoints(0, 1, parentPoint.x(), parentPoint.y()); if ( parentRow == childRow ) { if (parentCol == childCol - 1 || rowFree(parentRow, parentCol+1, childCol-1)) { a.putPoints(1, 1, childPoint.x(), childPoint.y()); } else // go around below { a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), // stop short parentPoint.x()+(wgap/2), parentPoint.y()+3, // right/down parentPoint.x()+(wgap/2), parentBottom+(hgap/2)-3, // stop short parentPoint.x()+(wgap/2)+3, parentBottom+(hgap/2), // right/down childPoint.x()-(wgap/2)-3, parentBottom+(hgap/2), // stop short childPoint.x()-(wgap/2), parentBottom+(hgap/2)-3, // right/up childPoint.x()-(wgap/2), childPoint.y()+3, // stop short childPoint.x()-(wgap/2)+3, childPoint.y(), // right/up childPoint.x(), childPoint.y()); } } else if ( parentRow > childRow ) { if (parentCol == childCol - 1) { a.putPoints(1, 5, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()-3, parentPoint.x()+wgap/2, childPoint.y()+3, parentPoint.x()+(wgap/2)+3, childPoint.y(), childPoint.x(), childPoint.y()); } else // go around above { a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()-3, parentPoint.x()+wgap/2, parentTop-(hgap/2)+3, parentPoint.x()+(wgap/2)+3, parentTop-(hgap/2), childPoint.x()-(wgap/2)-3, parentTop-hgap/2, childPoint.x()-(wgap/2), parentTop-(hgap/2)-3, childPoint.x()-wgap/2, childPoint.y()+3, childPoint.x()-(wgap/2)+3, childPoint.y(), childPoint.x(), childPoint.y()); } } else if ( parentRow < childRow ) { if (parentCol == childCol - 1) { a.putPoints(1, 5, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()+3, parentPoint.x()+wgap/2, childPoint.y()-3, parentPoint.x()+(wgap/2)+3, childPoint.y(), childPoint.x(), childPoint.y()); } else { a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()+3, parentPoint.x()+wgap/2, childTop-(hgap/2)-3, parentPoint.x()+(wgap/2)+3, childTop-(hgap/2), childPoint.x()-(wgap/2)-3, childTop-(hgap/2), childPoint.x()-(wgap/2), childTop-(hgap/2)+3, childPoint.x()-wgap/2, childPoint.y()-3, childPoint.x()-wgap/2+3, childPoint.y(), childPoint.x(), childPoint.y()); } } setPoints(a); } void PertRelationItem::setFinishFinishPoints() { //kdDebug()<exitPoint(Relation::FinishFinish); QPoint childPoint = m_childItem->entryPoint(Relation::FinishFinish); QPointArray a; a.putPoints(0, 1, parentPoint.x(), parentPoint.y()); if ( parentRow >= childRow ) { if (parentCol == childCol) { a.putPoints(1, 5, childPoint.x()+(wgap/2)-3, parentPoint.y(), childPoint.x()+(wgap/2), parentPoint.y()-3, childPoint.x()+wgap/2, childPoint.y()+3, childPoint.x()+(wgap/2)-3, childPoint.y(), childPoint.x(), childPoint.y()); } else if (parentCol < childCol) { a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), // stop short parentPoint.x()+(wgap/2), parentPoint.y()+3, // right/down parentPoint.x()+(wgap/2), parentBottom+(hgap/2)-3, // stop short parentPoint.x()+(wgap/2)+3, parentBottom+(hgap/2), // right/down childPoint.x()+(wgap/2)-3, parentBottom+(hgap/2), // stop short childPoint.x()+(wgap/2), parentBottom+(hgap/2)-3, // right/up childPoint.x()+(wgap/2), childPoint.y()+3, // stop short childPoint.x()+(wgap/2)-3, childPoint.y(), // left/up childPoint.x(), childPoint.y()); } } else // parentRow < choldRow { if (parentCol == childCol) { a.putPoints(1, 5, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()+3, parentPoint.x()+wgap/2, childPoint.y()-3, parentPoint.x()+(wgap/2)-3, childPoint.y(), childPoint.x(), childPoint.y()); } else if (parentCol < childCol) { if (rowFree(parentRow, parentCol+1, childCol)) a.putPoints(1, 5, childPoint.x()+(wgap/2)-3, parentPoint.y(), childPoint.x()+(wgap/2), parentPoint.y()+3, childPoint.x()+(wgap/2), childPoint.y()-3, childPoint.x()+(wgap/2)-3, childPoint.y(), childPoint.x(), childPoint.y()); else a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()+3, parentPoint.x()+wgap/2, childTop-(hgap/2)-3, parentPoint.x()+(wgap/2)+3, childTop-(hgap/2), childPoint.x()+(wgap/2)-3, childTop-(hgap/2), childPoint.x()+(wgap/2), childTop-(hgap/2)+3, childPoint.x()+(wgap/2), childPoint.y()-3, childPoint.x()+(wgap/2)-3, childPoint.y(), childPoint.x(), childPoint.y()); } else { a.putPoints(1, 9, parentPoint.x()+(wgap/2)-3, parentPoint.y(), parentPoint.x()+(wgap/2), parentPoint.y()+3, parentPoint.x()+wgap/2, childTop-(hgap/2)-3, parentPoint.x()+(wgap/2)+3, childTop-(hgap/2), childPoint.x()+(wgap/2)-3, childTop-(hgap/2), childPoint.x()+(wgap/2), childTop-(hgap/2)+3, childPoint.x()+wgap/2, childPoint.y()-3, childPoint.x()+wgap/2-3, childPoint.y(), childPoint.x(), childPoint.y()); } } setPoints(a); } void PertRelationItem::setStartStartPoints() { //kdDebug()<exitPoint(Relation::StartStart); QPoint childPoint = m_childItem->entryPoint(Relation::StartStart); QPointArray a; a.putPoints(0, 1, parentPoint.x(), parentPoint.y()); if ( parentRow > childRow ) { if (parentCol == childCol) // go up { a.putPoints(1, 4, parentPoint.x()-(wgap/2)+3, parentPoint.y(), parentPoint.x()-(wgap/2), parentPoint.y()-3, parentPoint.x()-(wgap/2), childPoint.y()+3, parentPoint.x()-(wgap/2)+3, childPoint.y()); } else // go above myself { a.putPoints(1, 8, parentPoint.x()-(wgap/2)+3, parentPoint.y(), parentPoint.x()-(wgap/2), parentPoint.y()-3, parentPoint.x()-(wgap/2), parentTop-(hgap/2)+3, parentPoint.x()-(wgap/2)+3, parentTop-(hgap/2), childPoint.x()-(wgap/2)-3, parentTop-(hgap/2), childPoint.x()-(wgap/2), parentTop-(hgap/2)-3, childPoint.x()-(wgap/2), childPoint.y()+3, childPoint.x()-(wgap/2)+3, childPoint.y()); } } else // go left/down { a.putPoints(1, 2, parentPoint.x()-(wgap/2)+3, parentPoint.y(), parentPoint.x()-(wgap/2), parentPoint.y()+3); if (parentCol == childCol) { a.putPoints(3, 2, parentPoint.x()-(wgap/2), childPoint.y()-3, parentPoint.x()-(wgap/2)+3, childPoint.y()); } else // go below myself { if (parentRow == childRow) // go up { a.putPoints(3, 6, parentPoint.x()-(wgap/2), parentBottom+hgap/2-3, parentPoint.x()-(wgap/2)+3, parentBottom+hgap/2, childPoint.x()-(wgap/2)-3, parentBottom+hgap/2, childPoint.x()-(wgap/2), parentBottom+hgap/2-3, childPoint.x()-(wgap/2), childPoint.y()+3, childPoint.x()-(wgap/2)+3, childPoint.y()); } else // go down { a.putPoints(3, 6, parentPoint.x()-(wgap/2), childTop-(hgap/2)-3, parentPoint.x()-(wgap/2)+3, childTop-hgap/2, childPoint.x()-(wgap/2)-3, childTop-hgap/2, childPoint.x()-(wgap/2), childTop-(hgap/2)+3, childPoint.x()-(wgap/2), childPoint.y()-3, childPoint.x()-(wgap/2)+3, childPoint.y()); } } } a.putPoints(a.size(), 1, childPoint.x(), childPoint.y()); setPoints(a); } void PertRelationItem::drawShape(QPainter &p) { //kdDebug()<parent()->name()<<" to "<child()->name()< 1&& a[pos-1].x() > a[pos].x()) xoffset = 3; QPoint pnt(a[pos].x()+xoffset, a[pos].y()-3); p.drawLine(a[pos], pnt); pnt.setY(a[pos].y()+3); p.drawLine(a[pos], pnt); } QPointArray PertRelationItem::areaPoints () const { QPointArray pa(4); int pw = (pen().width()+1)/2; if ( pw < 1 ) pw = 1; if ( pen() == NoPen ) pw = 0; pa[0] = QPoint(left-pw,top-pw); pa[1] = pa[0] + QPoint(right-left+pw*2,0); pa[2] = pa[1] + QPoint(0,bottom-top+pw*2); pa[3] = pa[0] + QPoint(0,bottom-top+pw*2); /* kdDebug()<parent()->name()<<" to "<child()->name()<allItems(); QCanvasItemList::Iterator it = list.begin(); for (; it != list.end(); ++it) { if ( (*it)->rtti() == PertProjectItem::RTTI || (*it)->rtti() == PertTaskItem::RTTI || (*it)->rtti() == PertMilestoneItem::RTTI ) { PertNodeItem *item = (PertNodeItem *)(*it); if ( item->row() == row ) { int col = item->column(); if (col >= startCol && col <= endCol) { //kdDebug()<name()), m_node(node), m_view(parent) { setExpandable(true); setOpen(true); } GanttViewSummaryItem::GanttViewSummaryItem(KDGanttViewItem *parent, Node *node) : KDGanttViewSummaryItem(parent, node->name()), m_node(node), m_view(0) { m_drawn = false; GanttViewSummaryItem *p = dynamic_cast(parent); if (p) m_view = p->ganttView(); setExpandable(true); setOpen(true); } void GanttViewSummaryItem::insertRelations(GanttView *view) { //kdDebug()< it(m_node->dependChildNodes()); for (; it.current(); ++it) { KDGanttViewItem *child = find(m_view->firstChild(), it.current()->child()); if (child) { KDGanttViewTaskLink *link = new KDGanttViewTaskLink(this, child, kdLinkType(it.current()->type())); //TODO i18n QString t = i18n("From: %1").arg(this->listViewText(0)); t += "\n" + i18n("To: %1").arg(child->listViewText(0)); if (it.current()->lag() > Duration::zeroDuration) { t += "\n" + i18n("Lag: %1").arg(it.current()->lag().toString(Duration::Format_i18nDayTime)); } link->setTooltipText(t); view->addTaskLink(link); } } } KDGanttViewItem *GanttViewSummaryItem::find(Node *node) { //kdDebug()<type() == Event) { GanttViewEventItem *i = static_cast(item); return i->find(node); } else if (item->type() == Task) { GanttViewTaskItem *i = static_cast(item); return i->find(node); } else if (item->type() == Summary) { GanttViewSummaryItem *i = static_cast(item); return i->find(node); } return 0; } //////////////////// GanttViewTaskItem ////////////////////////// GanttViewTaskItem::GanttViewTaskItem(KDGanttView *parent, KPlato::Task *task) : KDGanttViewTaskItem(parent, task->name()), m_task(task), m_view(parent) { } GanttViewTaskItem::GanttViewTaskItem(KDGanttViewItem *parent, KPlato::Task *task) : KDGanttViewTaskItem(parent, task->name()), m_task(task), m_view() { m_drawn = false; GanttViewSummaryItem *p = dynamic_cast(parent); if (p) m_view = p->ganttView(); } void GanttViewTaskItem::insertRelations(GanttView *view) { //kdDebug()< it(m_task->dependChildNodes()); for (; it.current(); ++it) { KDGanttViewItem *child = find(m_view->firstChild(), it.current()->child()); if (child) { KDGanttViewTaskLink *link = new KDGanttViewTaskLink(this, child, kdLinkType(it.current()->type())); //TODO i18n QString t = i18n("From: %1").arg(this->listViewText(0)); t += "\n" + i18n("To: %1").arg(child->listViewText(0)); if (it.current()->lag() > Duration::zeroDuration) { t += "\n" + i18n("Lag: %1").arg(it.current()->lag().toString(Duration::Format_i18nDayTime)); } link->setTooltipText(t); view->addTaskLink(link); } } } KDGanttViewItem *GanttViewTaskItem::find(Node *node) { //kdDebug()<type() == Event) { GanttViewEventItem *i = static_cast(item); return i->find(node); } else if (item->type() == Task) { GanttViewTaskItem *i= static_cast(item); return i->find(node); } else if (item->type() == Summary) { GanttViewSummaryItem *i = static_cast(item); return i->find(node); } return 0; // avoid warning } //////////////////// GanttViewEventItem ////////////////////////// GanttViewEventItem::GanttViewEventItem(KDGanttView *parent, KPlato::Task *task) : KDGanttViewEventItem(parent, task->name()), m_task(task), m_view(parent) { } GanttViewEventItem::GanttViewEventItem(KDGanttViewItem *parent, KPlato::Task *task) : KDGanttViewEventItem(parent, task->name()), m_task(task), m_view() { m_drawn = false; GanttViewSummaryItem *p = dynamic_cast(parent); if (p) m_view = p->ganttView(); } void GanttViewEventItem::insertRelations(GanttView *view) { //kdDebug()< it(m_task->dependChildNodes()); for (; it.current(); ++it) { KDGanttViewItem *child = find(m_view->firstChild(), it.current()->child()); if (child) { KDGanttViewTaskLink *link = new KDGanttViewTaskLink(this, child, kdLinkType(it.current()->type())); QString t = i18n("From: %1").arg(this->listViewText(0)); t += "\n" + i18n("To: %1").arg(child->listViewText(0)); if (it.current()->lag() > Duration::zeroDuration) { t += "\n" + i18n("Lag: %1").arg(it.current()->lag().toString(Duration::Format_i18nDayTime)); } link->setTooltipText(t); view->addTaskLink(link); } } } KDGanttViewItem *GanttViewEventItem::find(Node *node) { //kdDebug()<type() == Event) { GanttViewEventItem *i = static_cast(item); return i->find(node); } else if (item->type() == Task) { GanttViewTaskItem *i = static_cast(item); return i->find(node); } else if (item->type() == Summary) { GanttViewSummaryItem *i = static_cast(item); return i->find(node); } return 0; } } //KPlato namespace