diff options
Diffstat (limited to 'kdgantt/KDGanttViewSubwidgets.cpp')
-rw-r--r-- | kdgantt/KDGanttViewSubwidgets.cpp | 4048 |
1 files changed, 4048 insertions, 0 deletions
diff --git a/kdgantt/KDGanttViewSubwidgets.cpp b/kdgantt/KDGanttViewSubwidgets.cpp new file mode 100644 index 000000000..d35f7eba5 --- /dev/null +++ b/kdgantt/KDGanttViewSubwidgets.cpp @@ -0,0 +1,4048 @@ +/* -*- Mode: C++ -*- + $Id$ + KDGantt - a multi-platform charting engine +*/ + +/**************************************************************************** + ** Copyright (C) 2002-2004 Klarälvdalens Datakonsult AB. All rights reserved. + ** + ** This file is part of the KDGantt library. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid commercial KDGantt licenses may use this file in + ** accordance with the KDGantt Commercial License Agreement provided with + ** the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.klaralvdalens-datakonsult.se/Public/products/ for + ** information about KDGantt Commercial License Agreements. + ** + ** Contact info@klaralvdalens-datakonsult.se if any conditions of this + ** licensing are not clear to you. + ** + ** As a special exception, permission is given to link this program + ** with any edition of Qt, and distribute the resulting executable, + ** without including the source code for Qt in the source distribution. + ** + **********************************************************************/ + + +#include "KDGanttViewSubwidgets.h" +#include "KDGanttViewEventItem.h" +#include "KDGanttViewSummaryItem.h" +#include "KDGanttViewTaskItem.h" +#ifndef KDGANTT_MASTER_CVS +#include "KDGanttViewSubwidgets.moc" +#endif + +#include <qlabel.h> +#include <qheader.h> +#include <qpainter.h> +#include <qrect.h> +#include <qtooltip.h> +#include <qapplication.h> +#include <qdrawutil.h> +#include <qpalette.h> +#include <qdragobject.h> +#include <qptrlist.h> +#include <qpen.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kcalendarsystem.h> +#include <kdebug.h> + +KDTimeTableWidget:: KDTimeTableWidget( QWidget* parent,KDGanttView* myGantt) + : QCanvas (parent) +{ + myGanttView = myGantt; + taskLinksVisible = true; + flag_blockUpdating = false; + int_blockUpdating = 0; + gridPen.setStyle(Qt::DotLine); + gridPen.setColor(QColor(100,100,100)); + maximumComputedGridHeight = 0; + denseLineCount = 0; + denseLineBrush = QBrush( QColor ( 240,240,240 )); + noInfoLineBrush = QBrush( QColor ( 100,100,100 ), Qt::FDiagPattern ); + pendingHeight = 0; + pendingWidth = 0; + retune(256); + resize(1,1); +} + +QPtrList<KDGanttViewTaskLink> KDTimeTableWidget::taskLinks() +{ + return myTaskLinkList; +} + +void KDTimeTableWidget::clearTaskLinks() +{ + // cannot use clear() here, as tasklinks will remove themselves from my list when deleted! + QPtrListIterator<KDGanttViewTaskLink> it(myTaskLinkList); + while (it.current()) { + delete it.current(); + } + +} + +void KDTimeTableWidget::resetWidth( int wid ) +{ + if ( wid == width() ) { + if (pendingHeight) + pendingWidth = wid; + else + pendingWidth = 0; + return; + } + if ( ! pendingHeight ) + pendingHeight = height(); + pendingWidth = wid; + updateMyContent(); +} + +void KDTimeTableWidget::checkHeight( int hei ) +{ + if( hei < height() ) + return; + if ( pendingHeight < hei+100) + pendingHeight = hei+100; + if ( ! pendingWidth ) + pendingWidth = width(); + maximumComputedGridHeight = 0; //force recomputing all + updateMyContent(); +} + + +void KDTimeTableWidget::setNoInformationBrush( const QBrush& brush ) +{ + noInfoLineBrush = brush; + updateMyContent(); +} +QBrush KDTimeTableWidget::noInformationBrush() const +{ + return noInfoLineBrush; +} + +void KDTimeTableWidget::removeItemFromTasklinks( KDGanttViewItem* item) +{ + QPtrListIterator<KDGanttViewTaskLink> it((myTaskLinkList)); + for ( ; it.current(); ++it ) { + it.current()->removeItemFromList( item ); + } +} + +void KDTimeTableWidget::expandItem( QListViewItem * item) +{ + item->invalidateHeight () ; + //qApp->processEvents(); + updateMyContent(); +} +void KDTimeTableWidget::collapseItem( QListViewItem * item) +{ + item->invalidateHeight () ; + //qApp->processEvents(); + updateMyContent(); +} + +void KDTimeTableWidget::highlightItem( QListViewItem * item ) +{ + static bool itemwashighlighted; + static KDGanttViewItem* highlightedItem = 0; + if (highlightedItem) + highlightedItem->setHighlight(itemwashighlighted); + highlightedItem = ( KDGanttViewItem*)item; + itemwashighlighted = highlightedItem->highlight(); + highlightedItem->setHighlight(true); + item->invalidateHeight () ; + myGanttView->myListView->contentsY(); + updateMyContent(); +} +int KDTimeTableWidget::computeHeight() +{ + // compute height of ListView + // show only items shown in ListView + int hei = 0; + KDGanttViewItem* temp; + temp = myGanttView->firstChild(); + while (temp) { + hei += temp->computeHeight(); + temp = temp->nextSibling(); + } + // set hei to 1 to avoid canavs to be a null pixmap + if (hei == 0) { + hei = 1; + } + //qDebug("COMPUTED HEI %d ", hei); + emit heightComputed( hei ); + return hei; +} +void KDTimeTableWidget::computeVerticalGrid() +{ + // recompute the vertical grid + // compute the vertical grid + // if we have too much lines, hide them + //qDebug("computeVerticalGrid() "); + int cw = myGanttView->myTimeHeader->myGridMinorWidth; + int i = 0; + int h ; + if (pendingHeight > height() ) + h = pendingHeight; + else + h = height(); + int wid; + if ( pendingWidth ) + wid = pendingWidth; + else + wid = width(); + KDCanvasLine* templine; + KDCanvasRectangle* temprect; + QColor colcol; + QPen colPen; + bool colorIterator = true; + + + if (myGanttView->showMinorTicks()){//minor + colPen.setWidth(cw); + QPtrListIterator<KDCanvasRectangle> itcol(columnColorList); + QPtrListIterator<KDCanvasLine> itgrid(verGridList); + for ( ; itgrid.current(); ++itgrid ) { + if (i < wid) { + itgrid.current()->setPoints(i,0,i,h); + itgrid.current()->show(); + + if (myGanttView->myTimeHeader->getColumnColor(colcol,i,i+cw)) + { + + colPen.setColor(colcol); + if (colorIterator) + colorIterator = itcol.current(); + if (colorIterator) + {/* + itcol.current()->setPen(colPen); + itcol.current()->setPoints(i+(cw/2),0,i+(cw/2),h); + */ + + itcol.current()->setPen( QPen::NoPen ); + itcol.current()->setBrush( QBrush( colcol, SolidPattern) ); + itcol.current()->setSize(cw ,h ); + itcol.current()->move( i, 0 ); + itcol.current()->show(); + ++itcol; + } else { + + /* + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(colPen); + templine->setPoints(i+(cw/2),0,i+(cw/2),h); + */ + temprect = new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + temprect->setPen( QPen::NoPen ); + temprect->setBrush( QBrush( colcol, SolidPattern) ); + temprect->setSize(cw ,h ); + temprect->move( i, 0 ); + temprect->setZ(-20); + temprect->show(); + columnColorList.append(temprect); + } + } + i += cw; + } else { + itgrid.current()->hide(); + } + } + // create additional Lines for vertical grid + for ( ;i < wid;i += cw) { + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(gridPen); + templine->setPoints(i,0,i,h); + templine->setZ(0); + templine->show(); + verGridList.append(templine); + if (myGanttView->myTimeHeader->getColumnColor(colcol,i,i+cw)) + { + colPen.setColor(colcol); + if (colorIterator) + colorIterator = itcol.current(); + if (colorIterator) + {/* + itcol.current()->setPen(colPen); + itcol.current()->setPoints(i+(cw/2),0,i+(cw/2),h); + */ + itcol.current()->setPen( QPen::NoPen ); + itcol.current()->setBrush( QBrush( colcol, SolidPattern) ); + itcol.current()->setSize(cw ,h ); + itcol.current()->move( i, 0 ); + itcol.current()->show(); + ++itcol; + } else { + temprect = new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + temprect->setPen( QPen::NoPen ); + temprect->setBrush( QBrush( colcol, SolidPattern) ); + temprect->setSize(cw ,h ); + temprect->move( i, 0 ); + temprect->setZ(-20); + temprect->show(); + columnColorList.append(temprect); + /* + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(colPen); + templine->setPoints(i+(cw/2),0,i+(cw/2),h); + templine->setZ(-20); + templine->show(); + columnColorList.append(templine); + */ + } + } + } + if (colorIterator) + for ( ; itcol.current(); ++itcol ) + itcol.current()->hide(); + } else {//major + if (myGanttView->showMajorTicks()) { + QValueList<int>::iterator intIt = myGanttView->myTimeHeader->majorTicks.begin(); + QValueList<int>::iterator intItEnd = myGanttView->myTimeHeader->majorTicks.end(); + QPtrListIterator<KDCanvasRectangle> itcol(columnColorList); + QPtrListIterator<KDCanvasLine> itgrid(verGridList); + int left = 0; + for ( ; itgrid.current(); ++itgrid ) { + if (intIt != intItEnd) { + left = (*intIt); + ++intIt; + itgrid.current()->setPoints(left,0,left,h); + itgrid.current()->show(); + //int right = (*intIt); + if ((*intIt)) + if (myGanttView->myTimeHeader->getColumnColor(colcol,left,(*intIt) )) + { + int mid = (-left+(*intIt)); + colPen.setColor(colcol); + colPen.setWidth((*intIt)-left); + if (colorIterator) + colorIterator = itcol.current(); + if (colorIterator) + {/* + itcol.current()->setPen(colPen); + itcol.current()->setPoints(i+mid,0,mid,h); + */ + itcol.current()->setPen( QPen::NoPen ); + itcol.current()->setBrush( QBrush( colcol, SolidPattern) ); + itcol.current()->setSize(mid ,h ); + itcol.current()->move( left, 0 ); + itcol.current()->show(); + ++itcol; + } else { + temprect = new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + temprect->setPen( QPen::NoPen ); + temprect->setBrush( QBrush( colcol, SolidPattern) ); + temprect->setSize(mid,h ); + temprect->move( left, 0 ); + temprect->setZ(-20); + temprect->show(); + columnColorList.append(temprect); + /* + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(colPen); + templine->setPoints(mid,0,i+mid,h); + templine->setZ(-20); + templine->show(); + columnColorList.append(templine); + */ + + } + } + + } else { + itgrid.current()->hide(); + } + } + KDCanvasLine* templine; + // create additional Lines for vertical grid + for ( ;intIt != intItEnd ;++intIt) { + + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(gridPen); + templine->setPoints((*intIt),0,(*intIt),h); + templine->setZ(0); + templine->show(); + verGridList.append(templine); + if ((*intIt)) + if (myGanttView->myTimeHeader->getColumnColor(colcol,left,(*intIt))) + { + int mid = (-left+(*intIt)); + colPen.setColor(colcol); + colPen.setWidth((*intIt)-left); + if (colorIterator) + colorIterator = itcol.current(); + if (colorIterator) + {/* + itcol.current()->setPen(colPen); + itcol.current()->setPoints(i+mid,0,mid,h); + */ + itcol.current()->setPen( QPen::NoPen ); + itcol.current()->setBrush( QBrush( colcol, SolidPattern) ); + itcol.current()->setSize(mid ,h ); + itcol.current()->move( left, 0 ); + itcol.current()->show(); + ++itcol; + } else { + temprect = new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + temprect->setPen( QPen::NoPen ); + temprect->setBrush( QBrush( colcol, SolidPattern) ); + temprect->setSize(mid ,h ); + temprect->move( left, 0 ); + temprect->setZ(-20); + temprect->show(); + columnColorList.append(temprect); + /* + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(colPen); + templine->setPoints(mid,0,i+mid,h); + templine->setZ(-20); + templine->show(); + columnColorList.append(templine); + */ + } + } + left = (*intIt); + } + if (colorIterator) + for ( ; itcol.current(); ++itcol ) { + itcol.current()->hide(); + } + + } + else { + //hideall + QPtrListIterator<KDCanvasLine> itgrid(verGridList); + for ( ; itgrid.current(); ++itgrid ) { + itgrid.current()->hide(); + } + QPtrListIterator<KDCanvasRectangle> itcol(columnColorList); + for ( ; itcol.current(); ++itcol ) { + itcol.current()->hide(); + } + } + } +} +void KDTimeTableWidget::computeHorizontalGrid() +{ + // compute horizontal grid + //qDebug("computeHorizontalGrid() "); + KDGanttViewItem* temp = myGanttView->firstChild(); + int wid; + if ( pendingWidth ) + wid = pendingWidth; + else + wid = width(); + KDCanvasLine* templine; + QPtrListIterator<KDCanvasLine> ithor(horGridList); + if ( ithor.current() ) { + templine = ithor.current(); + ++ithor; + } else { + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(gridPen); + templine->setZ(0); + horGridList.append(templine); + } + templine->setPoints(0,0,wid,0); + templine->show(); + int posY; + while ( temp ) { + posY = temp->itemPos() + temp->height(); + if ( ithor.current() ) { + templine = ithor.current(); + ++ithor; + } else { + //new vertical grid line + templine = new KDCanvasLine(this,0,Type_is_KDGanttGridItem); + templine->setPen(gridPen); + templine->setZ(0); + horGridList.append(templine); + } + if ( templine->endPoint() != QPoint(wid,posY )) + templine->setPoints(0,posY,wid,posY ); + if ( !templine->isVisible() ) + templine->show(); + //QString ts = "asGroup"; + //if (!temp->displaySubitemsAsGroup() ) + // ts = " NOT asGroup"; + //qDebug("temp name %s %s", temp->listViewText(0).latin1(), ts.latin1()); + + temp = temp->itemBelow (); + } + while ( ithor.current() ) { + if ( ithor.current()->isVisible() ) + ithor.current()->hide(); + ++ithor; + } +} + +void KDTimeTableWidget::computeDenseLines() +{ + KDGanttViewItem* temp = myGanttView->firstChild(); + int wid; + if ( pendingWidth ) + wid = pendingWidth; + else + wid = width(); + QPtrListIterator<KDCanvasRectangle> ithordense(horDenseList); + KDCanvasRectangle* denseLine; + int tempDenseLineCount = 0; + while ( temp ) { + if ( temp->isVisible() ) { + ++tempDenseLineCount; + if ( tempDenseLineCount == denseLineCount ) { + tempDenseLineCount = 0; + if ( ithordense.current() ) { + denseLine = ithordense.current(); + ++ithordense; + } else { + denseLine =new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + denseLine->setZ(-2); + horDenseList.append( denseLine ); + } + if ( denseLine->rect() != QRect(0, temp->itemPos(),wid, temp->height()) ) { + denseLine->move( 0, temp->itemPos() ); + denseLine->setSize( wid, temp->height()); + } + if (denseLine->brush() != denseLineBrush ) { + denseLine->setPen( QPen( Qt::NoPen ) ); + denseLine->setBrush( denseLineBrush); + } + if (!denseLine->isVisible() ) + denseLine->show(); + + } else { + ; + } + } + temp = temp->itemBelow (); + } + while ( ithordense.current() ) { + if ( ithordense.current()->isVisible() ) { + ithordense.current()->hide(); + } + ++ithordense; + } +} +void KDTimeTableWidget::computeShowNoInformation() +{ + KDGanttViewItem* temp = myGanttView->firstChild(); + int wid; + if ( pendingWidth ) + wid = pendingWidth; + else + wid = width(); + QPtrListIterator<KDCanvasRectangle> itnoinfo(showNoInfoList); + KDCanvasRectangle* noInfoLine; + while ( temp ) { + if ( temp->showNoInformation() ) { + if ( itnoinfo.current() ) { + noInfoLine = itnoinfo.current(); + ++itnoinfo; + } else { + noInfoLine =new KDCanvasRectangle(this,0,Type_is_KDGanttGridItem); + showNoInfoList.append( noInfoLine ); + noInfoLine->setZ(-1); + } + noInfoLine->move( 0, temp->itemPos() ); + noInfoLine->setSize( wid, temp->height()); + noInfoLine->setPen( QPen( Qt::NoPen ) ); + noInfoLine->setBrush( noInfoLineBrush); + noInfoLine->show(); + } + temp = temp->itemBelow (); + } + while ( itnoinfo.current() ) { + itnoinfo.current()->hide(); + ++itnoinfo; + } + +} + +void KDTimeTableWidget::computeTaskLinks() +{ + //compute and show tasklinks + QPtrListIterator<KDGanttViewTaskLink> it((myTaskLinkList)); + for ( ; it.current(); ++it ) { + if (it.current()->isVisible()) + it.current()->showMe(true); + else + it.current()->showMe(false); + } +} + +// updateMyContent() can be blocked by blockUpdating( true ) or inc_blockUpdating() +// updateMyContent() is blocked, if the GanttView is hidden after startup + +void KDTimeTableWidget::updateMyContent() +{ + if ( flag_blockUpdating || int_blockUpdating ) { + // qDebug("KDTimeTableWidget::updateMyContent() blocked! "); + return; + } + //qDebug("KDTimeTableWidget::updateMyContent() ********************************* "); + /* + // debug output + KDGanttViewItem* temp = myGanttView->firstChild(); + while (temp != 0) { + temp->printinfo(" " ); + temp = temp->nextSibling(); + } + */ + int hei = computeHeight(); + minimumHeight = hei; + int viewport_hei = myGanttView->myCanvasView->viewport()->height(); + if ( viewport_hei > hei ) + hei = viewport_hei + 100; + if ( myGanttView->myTimeHeader->registerStartTime() ) + return; // try again via timeheader computeTicks(); + if ( myGanttView->myTimeHeader->registerEndTime() ) + return; // try again via timeheader computeTicks(); + if ( hei > height() ) { + if ( ! pendingWidth ) + pendingWidth = width(); + if ( pendingHeight < hei ) + pendingHeight = hei; + } + if (pendingHeight > hei ) + hei = pendingHeight; + if (hei > maximumComputedGridHeight) + { + maximumComputedGridHeight = hei; + // compute the background interval lines + myGanttView->myTimeHeader->computeIntervals( hei ); + //compute VerticalGrid and column color + computeVerticalGrid(); + } + computeTaskLinks(); + computeHorizontalGrid(); + computeDenseLines(); + computeShowNoInformation(); + //setAllChanged(); + update(); + if (pendingWidth && pendingHeight ) { + resize( pendingWidth, pendingHeight ); + pendingWidth = 0; + pendingHeight = 0; + emit heightComputed( 0 ); + + } + pendingWidth = 0; + pendingHeight = 0; + //qDebug("KDTimeTableWidget::updateMyContent() -------------------------"); +} +// used for blocking recursive methods +// e.g. KDGanttViewItem::setHighlight() and displaySubitemsAsGroup() == true + +void KDTimeTableWidget::inc_blockUpdating( ) +{ + ++ int_blockUpdating; +} +// used for blocking recursive methods +void KDTimeTableWidget::dec_blockUpdating( ) +{ + -- int_blockUpdating; +} +// if false(i.e. unblock), sets int_blockUpdating to 0 +void KDTimeTableWidget::setBlockUpdating( bool block ) +{ + if ( !block ) + int_blockUpdating = 0; + flag_blockUpdating = block; +} +bool KDTimeTableWidget::blockUpdating() +{ + return flag_blockUpdating; +} + +void KDTimeTableWidget::setShowTaskLinks( bool show ) +{ + taskLinksVisible = show; + updateMyContent(); +} +bool KDTimeTableWidget::showTaskLinks() +{ + return taskLinksVisible; +} +void KDTimeTableWidget::setHorBackgroundLines( int count, QBrush brush ) +{ + denseLineBrush = brush; + denseLineCount = 0; + if ( count > 1 ) + denseLineCount = count; +} + + +int KDTimeTableWidget::horBackgroundLines( QBrush& brush ) +{ + brush = denseLineBrush; + return denseLineCount; +} + +int KDTimeTableWidget::getCoordX( QDateTime dt ) { + return myGanttView->myTimeHeader->getCoordX(dt); +} + +/* *************************************************************** + KDTimeHeaderWidget:: KDTimeHeaderWidget + ***************************************************************** */ +KDTimeHeaderWidget:: KDTimeHeaderWidget( QWidget* parent,KDGanttView* gant ) + : QWidget (parent) +{ + myToolTip = new KDTimeHeaderToolTip(this,this); + mySizeHint = 0; + myGanttView = gant; + flagDoNotRecomputeAfterChange = true; + QDateTime start = (QDateTime::currentDateTime ()).addSecs(-3600); + setHorizonStart(start); + setHorizonEnd( start.addSecs(3600*2)); + flagStartTimeSet = false; + flagEndTimeSet = false; + myCenterDateTime = QDateTime::currentDateTime (); + setScale(KDGanttView::Auto); + //setScale(KDGanttView::Hour); + myMaxScale = KDGanttView::Month; + myMinScale = KDGanttView::Minute; + myAutoScaleMinorTickcount = 100; + setMajorScaleCount( 1 ); + setMinorScaleCount( 1); + setMinimumColumnWidth( 5 ); + setYearFormat(KDGanttView::FourDigit ); + setHourFormat( KDGanttView::Hour_12 ); + myZoomFactor = 1.0; + setWeekendBackgroundColor(QColor(220,220,220) ); + setWeekendDays( 6, 7 ); + myGridMinorWidth = 0; + myPopupMenu = new QPopupMenu(this); + QPopupMenu * zoomPopupMenu = new QPopupMenu(this); + myPopupMenu->insertItem (i18n("Zoom"),zoomPopupMenu, 1); + zoomPopupMenu->insertItem( i18n("Zoom to 100%"),this, SLOT(setSettings(int)),0 ,21,21 ); + zoomPopupMenu->insertItem( i18n("Zoom to Fit"),this, SLOT(setSettings(int)),0 ,20,20 ); + zoomPopupMenu->insertItem( i18n("Zoom In (x 2)"),this, SLOT(setSettings(int)),0 ,22,22 ); + zoomPopupMenu->insertItem( i18n("Zoom In (x 6)"),this, SLOT(setSettings(int)),0 ,24,24 ); + zoomPopupMenu->insertItem( i18n("Zoom In (x 12)"),this, SLOT(setSettings(int)),0 ,26,26 ); + zoomPopupMenu->insertItem( i18n("Zoom Out (x 1/2)"),this, SLOT(setSettings(int)),0 ,23,23 ); + zoomPopupMenu->insertItem( i18n("Zoom Out (x 1/6)"),this, SLOT(setSettings(int)),0 ,25,25 ); + zoomPopupMenu->insertItem( i18n("Zoom Out (x 1/12)"),this, SLOT(setSettings(int)),0 ,27,27 ); + scalePopupMenu = new QPopupMenu(this); + myPopupMenu->insertItem (i18n("Scale"),scalePopupMenu, 2); + scalePopupMenu->insertItem( i18n("Minute"),this, SLOT(setSettings(int)),0 ,1,1 ); + scalePopupMenu->insertItem( i18n("Hour"),this, SLOT(setSettings(int)),0 ,2,2 ); + scalePopupMenu->insertItem( i18n("Day"),this, SLOT(setSettings(int)),0 ,3,3 ); + scalePopupMenu->insertItem( i18n("Week"),this, SLOT(setSettings(int)),0 ,4,4 ); + scalePopupMenu->insertItem( i18n("Month"),this, SLOT(setSettings(int)),0 ,5,5 ); + scalePopupMenu->insertItem( i18n("Auto"),this, SLOT(setSettings(int)),0 ,6,6 ); + scalePopupMenu->setCheckable ( true ); + timePopupMenu = new QPopupMenu(this); + myPopupMenu->insertItem (i18n("Time Format"),timePopupMenu, 3); + timePopupMenu->insertItem( i18n("24 Hour"),this, SLOT(setSettings(int)),0 ,40,40 ); + timePopupMenu->insertItem( i18n("12 PM Hour"),this, SLOT(setSettings(int)),0 ,41,41 ); + timePopupMenu->insertItem( i18n("24:00 Hour"),this, SLOT(setSettings(int)),0 ,42,42 ); + yearPopupMenu = new QPopupMenu(this); + myPopupMenu->insertItem (i18n("Year Format"),yearPopupMenu, 4); + yearPopupMenu->insertItem( i18n("Four Digit"),this, SLOT(setSettings(int)),0 ,50,50 ); + yearPopupMenu->insertItem( i18n("Two Digit"),this, SLOT(setSettings(int)),0 ,51,51 ); + yearPopupMenu->insertItem( i18n("Two Digit Apostrophe"),this, SLOT(setSettings(int)),0 ,52,52 ); + yearPopupMenu->insertItem( i18n("No Date on Minute/Hour Scale"),this, SLOT(setSettings(int)),0 ,53,53 ); + + gridPopupMenu = new QPopupMenu(this); + myPopupMenu->insertItem (i18n("Grid"),gridPopupMenu,5); + gridPopupMenu->insertItem( i18n("Show Minor Grid"),this, SLOT(setSettings(int)),0 ,10,10 ); + gridPopupMenu->insertItem( i18n("Show Major Grid"),this, SLOT(setSettings(int)),0 ,11,11 ); + gridPopupMenu->insertItem( i18n("Show No Grid"),this, SLOT(setSettings(int)),0 ,12,12 ); + myPopupMenu->insertItem( i18n("Print"),this, SLOT(setSettings(int)),0 ,30,30 ); + connect(myPopupMenu, SIGNAL ( aboutToShow () ) , this, SLOT( preparePopupMenu() )) ; + flagZoomToFit = false; + setShowMinorTicks( true ); + myRealEnd = myHorizonEnd; + myRealStart = myHorizonStart; + autoComputeTimeLine = true; + flagDoNotRecomputeAfterChange = false; + flagDoNotRepaintAfterChange = false; + setShowPopupMenu(false,false,false,false,false,false,false); + for (int j =1;j<8;++j) + weekdayColor[j] = Qt::white; + myMinimumWidth = 0; + mouseDown = false; + beginMouseDown = 0; + endMouseDown = 0; +} + +KDTimeHeaderWidget::~KDTimeHeaderWidget() +{ + delete myToolTip; +} +void KDTimeHeaderWidget::preparePopupMenu() +{ + myPopupMenu->setItemVisible ( 1, flagShowZoom ); + myPopupMenu->setItemVisible ( 2, flagShowScale ); + myPopupMenu->setItemVisible ( 3, flagShowTime ); + myPopupMenu->setItemVisible ( 4, flagShowYear ); + myPopupMenu->setItemVisible ( 5, flagShowGrid); + myPopupMenu->setItemVisible ( 30, flagShowPrint ); + if (flagZoomToFit) + myPopupMenu->changeItem( 1, i18n("Zoom (Fit)")); + else + myPopupMenu->changeItem( 1, i18n("Zoom (%1)").arg( QString::number( zoomFactor(), 'f',3) ) ); + int i = 0; + int id; + while ( ( id = scalePopupMenu->idAt( i++ )) >= 0 ) { + scalePopupMenu->setItemChecked ( id, false ); + } + scalePopupMenu->setItemChecked ( scalePopupMenu->idAt ( (int)( scale()) ), true ); + i = 0; + while ( ( id = timePopupMenu->idAt( i++ )) >= 0 ) { + timePopupMenu->setItemChecked ( id, false ); + } + timePopupMenu->setItemChecked ( timePopupMenu->idAt ( (int)( hourFormat()) ), true ); + i = 0; + while ( ( id = yearPopupMenu->idAt( i++ )) >= 0 ) { + yearPopupMenu->setItemChecked ( id, false ); + } + yearPopupMenu->setItemChecked ( yearPopupMenu->idAt ( (int)( yearFormat()) ), true ); + i = 0; + while ( ( id = gridPopupMenu->idAt( i++ )) >= 0 ) { + gridPopupMenu->setItemChecked ( id, false ); + } + + gridPopupMenu->setItemChecked ( gridPopupMenu->idAt ( 0 ), showMinorTicks() ); + gridPopupMenu->setItemChecked ( gridPopupMenu->idAt ( 1 ), showMajorTicks() ); + gridPopupMenu->setItemChecked ( gridPopupMenu->idAt ( 2 ), + !(showMajorTicks() || showMinorTicks()) ); + + +} + +QString KDTimeHeaderWidget::getToolTipText(QPoint p) +{ + return KGlobal::locale()->formatDateTime(getDateTimeForIndex(p.x())); +} +void KDTimeHeaderWidget::addTickRight( int num ) +{ + int secs = ((num*getTickTime())-30); + setHorizonEnd(getDateTimeForIndex(width()).addSecs(secs)); + //qApp->processEvents(); +} + +void KDTimeHeaderWidget::addTickLeft( int num ) +{ + int secs = ((num*getTickTime())-30); + setHorizonStart(getDateTimeForIndex(0).addSecs(-secs)); + //qApp->processEvents(); +} +// the time in secs of one minor grid tick +int KDTimeHeaderWidget::getTickTime() +{ + return getDateTimeForIndex(0).secsTo(getDateTimeForIndex(myGridMinorWidth)); +} + + +void KDTimeHeaderWidget::checkWidth( int wid ) +{ + // we have to set the minimum width one pixel higher than the + // viewport width of the canvas view in order to + // avoid that the horiz. scrollbar of the canvasview is hidden + myMinimumWidth = wid + 1; + if ( myMinimumWidth > width() || + ( myMinimumWidth > mySizeHint && + myMinimumWidth < (width() - myGridMinorWidth )) ) + computeTicks(); + + // Update (horizontal) scrollbar, + // We probably come from an external resize and then we must + // calculate on basis of myCanvasView. + // (NOTE: we have disconnected the auto QScrollView scrollbar update) + if (myGanttView && myGanttView->myCanvasView) + myGanttView->myCanvasView->updateScrollBars(); +} + +bool KDTimeHeaderWidget::registerStartTime() +{ + + QListViewItemIterator it( myGanttView->myListView ); + if (!flagStartTimeSet) { + QDateTime temp , time; + KDGanttViewItem* item; + bool setNewTime = false; + item = (KDGanttViewItem*)myGanttView->myListView->firstChild(); + if ( item ) { + temp = item->startTime(); + time = temp; + // while ( item != 0) + for ( ; it.current(); ++it ) { + item = ( KDGanttViewItem* )it.current(); + if (item->isVisibleInGanttView) { + if ( !setNewTime ) + temp = item->startTime(); + switch( item->type() ) { + case KDGanttViewItem::Event: + time = ((KDGanttViewEventItem*)item)->leadTime(); + setNewTime = true; + break; + case KDGanttViewItem::Summary: + case KDGanttViewItem::Task: + time = item->startTime(); + setNewTime = true; + break; + default: + time = temp; + } + if ( time < temp) { + temp = time ; + } + } + } + if ( setNewTime ) + if ( myHorizonStart != temp) { + myHorizonStart = temp; + computeTicks(); + return true; + } + } + } + return false; +} + + +bool KDTimeHeaderWidget::registerEndTime() +{ + if (!flagEndTimeSet) { + QDateTime temp , time; + KDGanttViewItem* item; + bool setNewTime = false; + item = (KDGanttViewItem*)myGanttView->myListView->firstChild(); + if ( item ) { + temp = item->startTime(); + time = temp; + QListViewItemIterator it( myGanttView->myListView ); + for ( ; it.current(); ++it ) { + item = ( KDGanttViewItem* )it.current(); + if (item->isVisibleInGanttView) { + if ( !setNewTime ) + temp = item->startTime(); + switch( item->type() ) { + case KDGanttViewItem::Event: + time = ((KDGanttViewEventItem*)item)->startTime(); + setNewTime = true; + break; + case KDGanttViewItem::Summary: + time = item->endTime(); + if ( time < ((KDGanttViewSummaryItem*)item)->actualEndTime()) + time = ((KDGanttViewSummaryItem*)item)->actualEndTime(); + setNewTime = true; + break; + case KDGanttViewItem::Task: + time = item->endTime(); + setNewTime = true; + break; + default: + time = temp; + } + if ( time > temp) + temp = time ; + } + } + + if ( setNewTime ) + if (myHorizonEnd != temp ) { + myHorizonEnd = temp; + computeTicks(); + return true; + } + } + } + return false; +} + + +void KDTimeHeaderWidget::setShowPopupMenu( bool show, + bool showZoom, + bool showScale, + bool showTime, + bool showYear, + bool showGrid, + bool showPrint) +{ + flagShowPopupMenu = show; + flagShowZoom = showZoom; + flagShowScale = showScale; + flagShowTime = showTime; + flagShowYear = showYear; + flagShowGrid = showGrid; + flagShowPrint = showPrint; +} + + +bool KDTimeHeaderWidget::showPopupMenu() const +{ + return flagShowPopupMenu; +} + +void KDTimeHeaderWidget::setSettings(int i) +{ + + switch (i) { + case 1: + setScale(KDGanttView::Minute ); + break; + case 2: + setScale(KDGanttView::Hour ); + break; + case 3: + setScale(KDGanttView::Day ); + break; + case 4: + setScale(KDGanttView::Week ); + break; + case 5: + setScale(KDGanttView::Month ); + break; + case 6: + setScale(KDGanttView::Auto ); + break; + case 10: + setShowMinorTicks( true ); + break; + case 11: + setShowMajorTicks( true );{ + + } + break; + case 12: + setShowMajorTicks( false ); + setShowMinorTicks( false); + break; + case 20: + zoomToFit(); + break; + case 21: + zoom(1.0); + break; + case 22: + zoom(2.0,false); + break; + case 23: + zoom(0.5,false); + break; + case 24: + zoom(6.0,false); + break; + case 25: + zoom(0.16666,false); + break; + case 26: + zoom(12.0,false); + break; + case 27: + zoom(0.08333,false); + break; + case 30: + myGanttView->print(); + break; + case 40: + case 41: + case 42: + setHourFormat( (KDGanttView::HourFormat) (i - 40) ); + break; + case 50: + case 51: + case 52: + case 53: + setYearFormat( (KDGanttView::YearFormat) ( i - 50) ); + break; + + case 60: + + break; + + case 61: + + break; + + case 62: + + break; + + case 63: + + break; + + case 64: + + break; + } + // myGanttView->myTimeTable->updateMyContent(); +} +void KDTimeHeaderWidget::zoomToFit() +{ + flagZoomToFit = true; + computeTicks(); + // Since we have disconnected autoupdate of scrollbars, we must do it ourselves + if (myGanttView && myGanttView->myCanvasView) + myGanttView->myCanvasView->updateScrollBars(); +} +double KDTimeHeaderWidget::zoomFactor() +{ + return myZoomFactor; +} +double KDTimeHeaderWidget::secsFromTo( QDateTime begin, QDateTime end ) +{ + QDateTime temp; + double secs, days; + days = begin.daysTo(end); + temp = begin.addDays((int) days); + secs = temp.secsTo(end); + secs += days * 86400.0; + return secs; +} + + +void KDTimeHeaderWidget::zoomToSelection( QDateTime start, QDateTime end) +{ + if (start < myHorizonStart) { + myHorizonStart = start; + flagStartTimeSet = true; + //qDebug("myHorizonStart reset"); + } + if (end > myHorizonEnd) { + myHorizonEnd = end; + flagEndTimeSet = true; + //qDebug("myHorizonEnd reset "); + } + flagDoNotRepaintAfterChange = true;//avoid flicker + zoom(1.0); // set to 100% + int viewWid = myGanttView->myCanvasView->viewport()->width(); + int timeWid = getCoordX(end)-getCoordX(start); + double fac; + fac = ( (double)viewWid)/((double) timeWid ); + zoom (fac); + timeWid = getCoordX(end)-getCoordX(start); + int count = 0; + int lastScaleCount = 0; + while (timeWid >viewWid || ( ( myRealMinorScaleCount != lastScaleCount) && timeWid*2 < viewWid ) ) { + lastScaleCount = myRealMinorScaleCount; + fac = (fac * (double)viewWid)/(double)timeWid; + zoom (fac); + timeWid = getCoordX(end)-getCoordX(start); + if ( count++ > 10 ) { + //qDebug("Exiting while loop in zoomToSelection "); + break; + } + } + flagDoNotRepaintAfterChange = false; + updateTimeTable(); + repaint(); + moveTimeLineTo((getCoordX(start)-(viewWid-timeWid)/2)); + // Since we have disconnected autoupdate of scrollbars, we must do it ourselves + if (myGanttView && myGanttView->myCanvasView) + myGanttView->myCanvasView->updateScrollBars(); +} +void KDTimeHeaderWidget::moveTimeLineTo(int X) +{ + int Y = myGanttView->myCanvasView->contentsY (); + myGanttView->myCanvasView->setContentsPos (X, Y ); +} + +void KDTimeHeaderWidget::zoom(double factor, bool absolute) +{ + flagZoomToFit = false; + if ( factor < 0.000001 ) { + qDebug("KDGanttView::zoom() : Zoom factor to low. Nothing zoomed. "); + return; + } + double newZoom; + if (absolute) + newZoom = factor; + else + newZoom = myZoomFactor * factor; + double relativeZoom; + relativeZoom = newZoom / myZoomFactor; + + //qDebug("zooming relative %f ", relativeZoom); + //qDebug("zooming absolute %f ", newZoom); + int viewWid = myGanttView->myCanvasView->viewport()->width(); + if ( width() * relativeZoom < viewWid && ( newZoom > 1.01 || newZoom < 0.99 ) ) { + qDebug("KDGanttView::zoom() : Zoom factor to low for current horizon. "); + // qDebug("zooming relative %f, zooming absolute %f, viewWidth %d width %d ", relativeZoom, newZoom, viewWid, width() ); + return; + } + myZoomFactor = newZoom; + computeTicks(); + // Since we have disconnected autoupdate of scrollbars, we must do it ourselves + if (myGanttView && myGanttView->myCanvasView) + myGanttView->myCanvasView->updateScrollBars(); +} + +/*! + Sets the start of the horizon of the Gantt chart. If \a start is + null, the horizon start is computed automatically. + + \param start the start of the horizon + \sa horizonStart() +*/ +void KDTimeHeaderWidget::setHorizonStart( const QDateTime& start ) +{ + myHorizonStart = start; + flagStartTimeSet = true; + computeTicks(); +} + + +/*! + Returns the start of the horizon of the Gantt chart. + + \return the start of the horizon of the Gantt chart + \sa setHorizonStart() +*/ +QDateTime KDTimeHeaderWidget::horizonStart() const +{ + return myHorizonStart; +} + + +/*! + Sets the end of the horizon of the Gantt chart. If \a end is + null, the horizon end is computed automatically. + + \param end the end of the horizon + \sa setHorizonEnd() +*/ +void KDTimeHeaderWidget::setHorizonEnd( const QDateTime& start ) +{ + myHorizonEnd = start; + flagEndTimeSet = true; + computeTicks(); + +} + + +/*! + Returns the end of the horizon of the Gantt chart. + + \return the end of the horizon of the Gantt chart + \sa setHorizonEnd() +*/ +QDateTime KDTimeHeaderWidget::horizonEnd() const +{ + return myHorizonEnd; +} + + +/*! + Configures the unit of the lower scale of the header. The higher + unit is computed automatically. + Resets the zoomng factor to 1 (i.e. 100%). + + \param unit the unit of the lower scale of the header. + \sa scale() +*/ +void KDTimeHeaderWidget::setScale(Scale unit ) +{ + myScale = unit; + myZoomFactor = 1.0; + computeTicks(); + // Since we have disconnected autoupdate of scrollbars, we must do it ourselves + if (myGanttView && myGanttView->myCanvasView) + myGanttView->myCanvasView->updateHorScrollBar(); +} + + +/*! + Returns the unit of the lower scale of the header. + + \return the unit of the lower scale of the header. + \sa setScale() +*/ +KDTimeHeaderWidget::Scale KDTimeHeaderWidget::scale() const +{ + return myScale; +} + + +/*! + Sets the maximal allowed time scale of the lower scale of the header. + + \param unit the unit of the lower scale of the header. + \sa scale() +*/ +void KDTimeHeaderWidget::setMaximumScale( Scale unit ) +{ + myMaxScale = unit; + computeTicks(); +} + + +/*! + Returns the maximal allowed time scale of the lower scale of the header. + + \return the unit of the lower scale of the header. + \sa setScale() +*/ +KDTimeHeaderWidget::Scale KDTimeHeaderWidget::maximumScale() const +{ + return myMaxScale; +} + + +/*! + Sets the minimal allowed time scale of the lower scale of the header. + + \param unit the unit of the lower scale of the header. + \sa scale() +*/ +void KDTimeHeaderWidget::setMinimumScale( Scale unit ) +{ + myMinScale = unit; + computeTicks(); +} + + +/*! + Returns the minimal allowed time scale of the lower scale of the header. + + \return the unit of the lower scale of the header. + \sa setScale() +*/ +KDTimeHeaderWidget::Scale KDTimeHeaderWidget::minimumScale() const +{ + return myMinScale; +} + + +/*! + Sets the minimum width a column needs to have. If the size of the + Gantt chart and the scale would make it necessary to go below this + limit otherwise, the chart will automatically be made less exact. + + \param width the minimum column width + \sa minimumColumnWidth() +*/ +void KDTimeHeaderWidget::setMinimumColumnWidth( int width ) +{ + myMinimumColumWidth = width; + computeTicks(); +} + + +/*! + Returns the minimum width a column needs to have. + + \return the column minimum width + \sa setMinimumColumnWidth() +*/ +int KDTimeHeaderWidget::minimumColumnWidth() const +{ + return myMinimumColumWidth; +} + + +/*! + Specifies the format in which to display years. If no years are + shown, this method has no effect. + + \param format the year format + \sa yearFormat(), setHourFormat(), hourFormat() +*/ +void KDTimeHeaderWidget::setYearFormat( YearFormat format ) +{ + myYearFormat = format; + computeTicks(); +} + + +/*! + Returns the format in which to display years. + + \return the year format + \sa setYearFormat(), setHourFormat(), hourFormat() +*/ +KDTimeHeaderWidget::YearFormat KDTimeHeaderWidget::yearFormat() const +{ + return myYearFormat; +} + + +/*! + Specifies the format in which to display hours. If no hours are + shown, this method has no effect. + + \param format the hour format + \sa hourFormat(), setYearFormat(), yearFormat() +*/ +void KDTimeHeaderWidget::setHourFormat( HourFormat format ) +{ + myHourFormat = format; + computeTicks(); +} + + +/*! + Returns the format in which to display hours. + + \return the hour format + \sa setHourFormat(), setYearFormat(), yearFormat() +*/ +KDTimeHeaderWidget::HourFormat KDTimeHeaderWidget::hourFormat() const +{ + return myHourFormat; +} + + +/*! + Specifies whether ticks should be shown on the major scale. + + \param show true in order to show ticks, false in order to hide them + \sa showMajorTicks(), setShowMinorTicks(), showMinorTicks() +*/ +void KDTimeHeaderWidget::setShowMajorTicks( bool show ) +{ + flagShowMajorTicks = show; + if (show) { + setShowMinorTicks(false); + } + updateTimeTable(); +} + + +/*! + Returns whether ticks are shown on the major scale. + + \return true if ticks are shown on the major scale + \sa setShowMajorTicks(), setShowMinorTicks(), showMinorTicks() +*/ +bool KDTimeHeaderWidget::showMajorTicks() const +{ + return flagShowMajorTicks; +} + + +/*! + Specifies whether ticks should be shown on the minor scale. + + \param show true in order to show ticks, false in order to hide them + \sa showMinorTicks(), setShowMajorTicks(), showMajorTicks() +*/ +void KDTimeHeaderWidget::setShowMinorTicks( bool show ) +{ + flagShowMinorTicks = show; + if (show) + setShowMajorTicks(false ); + //repaintMe(); + updateTimeTable(); +} + + +/*! + Returns whether ticks are shown on the minor scale. + + \return true if ticks are shown on the minor scale + \sa setShowMinorTicks(), setShowMajorTicks(), showMajorTicks() +*/ +bool KDTimeHeaderWidget::showMinorTicks() const +{ + return flagShowMinorTicks; +} + + +/*! + Sets the background color for the column closest to \a column. + + \param column the column to set the background color for + \param color the background color + \sa columnBackgroundColor(), setWeekendBackgroundColor(), + weekendBackgroundColor() +*/ +void KDTimeHeaderWidget::setColumnBackgroundColor( const QDateTime& column, + const QColor& color, + Scale mini, Scale maxi ) +{ + ColumnColorList::iterator it; + for ( it = ccList.begin(); it != ccList.end(); ++it ) { + if ((*it).datetime == column) { + (*it).color = color; + (*it).minScaleView = mini; + (*it).maxScaleView = maxi; + return; + } + } + DateTimeColor newItem; + newItem.datetime = column; + newItem.color = color; + newItem.minScaleView = mini; + newItem.maxScaleView = maxi; + ccList.append(newItem); + updateTimeTable(); +} + +void KDTimeHeaderWidget::computeIntervals( int height ) +{ + IntervalColorList::const_iterator it; + for ( it = icList.begin(); it != icList.end(); ++it ) { + (*it)->layout( this, height ); + } +} + +void KDTimeHeaderWidget::addIntervalBackgroundColor( KDIntervalColorRectangle* newItem ) +{ + icList.append(newItem); + updateTimeTable(); +} + +#if 0 +bool KDTimeHeaderWidget::changeBackgroundInterval( const QDateTime& oldstart, + const QDateTime& oldend, + const QDateTime& newstart, + const QDateTime& newend ) +{ + IntervalColorList::iterator it; + for ( it = icList.begin(); it != icList.end(); ++it ) { + if ((*it).datetime == oldstart && (*it).end == oldend ) { + IntervalColorList::iterator it2; + for ( it2 = icList.begin(); it2 != icList.end(); ++it2 ) { + if ((*it2).datetime == newstart && (*it2).end == newend ) + return false; + } + (*it).datetime = newstart; + (*it).end = newend; + updateTimeTable(); + return true; + } + } + return false; +} +bool KDTimeHeaderWidget::deleteBackgroundInterval( const QDateTime& start, + const QDateTime& end) +{ + IntervalColorList::iterator it; + for ( it = icList.begin(); it != icList.end(); ++it ) { + if ((*it).datetime == start && (*it).end == end ) { + //delete (*it).canvasLine; + delete (*it).canvasRect; + icList.remove(it); + updateTimeTable(); + return true; + } + } + return false; +} + +void KDTimeHeaderWidget::setIntervalBackgroundColor( const QDateTime& start, + const QDateTime& end, + const QColor& color, + Scale mini , + Scale maxi ) +{ + + IntervalColorList::iterator it; + for ( it = icList.begin(); it != icList.end(); ++it ) { + if ((*it).datetime == start && (*it).end == end ) { + (*it).color = color; + (*it).minScaleView = mini; + (*it).maxScaleView = maxi; + return; + } + } + DateTimeColor newItem; + if ( start <= end ) { + newItem.datetime = start; + newItem.end = end; + } else { + newItem.datetime = end; + newItem.end = start; + } + newItem.color = color; + newItem.minScaleView = mini; + newItem.maxScaleView = maxi; + //newItem.canvasLine = new KDCanvasLine(myGanttView->myTimeTable,0,Type_is_KDGanttGridItem); + newItem.canvasRect = new KDCanvasRectangle(myGanttView->myTimeTable,0,Type_is_KDGanttGridItem); + newItem.canvasRect->setZ(-19); + icList.append(newItem); + updateTimeTable(); +} +#endif + +void KDTimeHeaderWidget::clearBackgroundColor() +{ + + IntervalColorList::iterator itic; + for ( itic = icList.begin(); itic != icList.end(); ++itic ) { + delete (*itic); + } + ccList.clear(); + icList.clear(); + updateTimeTable(); +} +QDateTime KDTimeHeaderWidget::getDateTimeForIndex(int X, bool local ) +{ + int coordX = X; + if ( !local ) { + QPoint p = QPoint ( X, 1 ); + coordX = myGanttView->myTimeHeaderScroll->viewportToContents(myGanttView->myTimeHeaderScroll->mapFromGlobal( p )).x(); + + } + double secs = (secsFromTo( myRealStart, myRealEnd ) * ((double)coordX))/(double)width(); + double days = secs/86400.0; + secs = secs - ( ((int) days) *86400.0 ); + return (myRealStart.addDays ( (int) days )).addSecs( (int) secs); +} + +//FIXME: This doesn't work quite intuitively (imho) when scale is day +// and each column containes more than 1 day: +// 1) If a column includes a weekend day, the whole column gets weekend color, +// 2) If a column includes 7 days, either *all* columns get weekend color, or +// *none* get weekend color (haven't figured out why) +// Proposal: Only use weekend color if the whole column is a weekend. +// Alt: Color the area that actually is the weekend. +bool KDTimeHeaderWidget::getColumnColor(QColor& col,int coordLow, int coordHigh) +{ + if (!flagShowMajorTicks && !flagShowMinorTicks) + return false; + QDateTime start,end; + start = getDateTimeForIndex(coordLow); + end = getDateTimeForIndex(coordHigh).addSecs(-1); + Scale tempScale = myRealScale; + if (flagShowMajorTicks) + switch (myRealScale) + { + case KDGanttView::Minute: tempScale = KDGanttView::Hour; break; + case KDGanttView::Hour: tempScale = KDGanttView::Day ; break; + case KDGanttView::Day: tempScale = KDGanttView::Week ; break; + case KDGanttView::Week: tempScale = KDGanttView::Month ; break; + case KDGanttView::Month: return false ; break; + case KDGanttView::Auto: return false ; break; + } + //check defined column color + ColumnColorList::iterator it; + for ( it = ccList.begin(); it != ccList.end(); ++it ) { + if ((*it).datetime >= start && (*it).datetime <= end) { + if (tempScale >= (*it).minScaleView && tempScale <= (*it).maxScaleView ) { + col = (*it).color; + return true; + } + } + } + + if (tempScale > KDGanttView::Day) return false; + + start = getDateTimeForIndex((coordLow+coordHigh)/2); + int day = start.date().dayOfWeek (); + //checkweekdaycolor + if (weekdayColor[day] != Qt::white) { + col = weekdayColor[day]; + return true; + } + //checkweekendcolor + int endday = myWeekendDaysEnd; + col = myWeekendBackgroundColor; + if (myWeekendDaysStart > myWeekendDaysEnd) + endday +=7; + if (day >= myWeekendDaysStart && day <= endday) { + return true; + } else { + if (day+7 >= myWeekendDaysStart && day+7 <= endday) { + return true; + } + } + return false; +} + +/*! + Returns the background color for the column closes to \a column. + + \param column the column to query the background color for + \return the background color of the specified column + \sa setColumnBackgroundColor(), setWeekendBackgroundColor(), + weekendBackgroundColor() +*/ +QColor KDTimeHeaderWidget::columnBackgroundColor( const QDateTime& column ) const +{ + QColor c; + c = white; + ColumnColorList::const_iterator ite; + for ( ite = ccList.begin(); ite != ccList.end(); ++ite ) { + if ((*ite).datetime == column) { + c = (*ite).color; + } + } + return c; +} + + +/*! + Specifies the background color for weekend days. If no individual + days are visible on the Gantt chart, this method has no visible + effect. + + \param color the background color to use for weekend days. + \sa weekendBackgroundColor(), setWeekendDays(), weekendDays() +*/ +void KDTimeHeaderWidget::setWeekendBackgroundColor( const QColor& color ) +{ + myWeekendBackgroundColor = color ; + updateTimeTable(); +} + + +/*! + Returns the background color for weekend days. + + \return the background color for weekend days + \sa setWeekendBackgroundColor(), setWeekendDays(), weekendDays() +*/ +QColor KDTimeHeaderWidget::weekendBackgroundColor() const +{ + return myWeekendBackgroundColor; +} + +/*! + Specifies the background color for week days. If no individual + days are visible on the Gantt chart, this method has no visible + effect. The days are specified as an interval of integer values + where 1 means Monday and 7 means Sunday. + + \param color the background color to use for weekend days. + \param weekday the day of the week (Monday = 1, Sunday = 7) + \sa weekendBackgroundColor(), setWeekendDays(), weekendDays() +*/ +void KDTimeHeaderWidget::setWeekdayBackgroundColor( const QColor& color, int weekday ) +{ + weekdayColor[weekday] = color; + updateTimeTable(); +} + + +/*! + Returns the background color for weekday days. + + \param the day of the week (Monday = 1, Sunday = 7) + \return the background color for weekend days + \sa setWeekendBackgroundColor(), setWeekendDays(), weekendDays() +*/ +QColor KDTimeHeaderWidget::weekdayBackgroundColor(int weekday) const +{ + return weekdayColor[weekday]; +} + + +/*! + Defines which days are considered weekends. The days are specified + as an interval of integer values where 1 means Monday and 7 means + Sunday. In order to define a weekend from Sunday to Monday, specify + (7,1). + + \param start the first day of the weekend + \param end the last day of the weekend + \sa weekendDays(), setWeekendBackgroundColor(), weekendBackgroundColor() +*/ +void KDTimeHeaderWidget::setWeekendDays( int start, int end ) +{ + myWeekendDaysStart = start; + myWeekendDaysEnd = end; + updateTimeTable(); +} + + +/*! + Returns which days are considered weekends. + + \param start in this parameter, the first day of the weekend is returned + \param end in this parameter, the end day of the weekend is returned + \sa setWeekendDays(), setWeekendBackgroundColor(), weekendBackgroundColor() +*/ +void KDTimeHeaderWidget::weekendDays( int& start, int& end ) const +{ + start = myWeekendDaysStart; + end = myWeekendDaysEnd ; +} + + + +/*! + Sets the number of ticks in the major scale. + + \param count the number of ticks in the major scale + \sa majorScaleCount(), setMinorScaleCount(), minorScaleCount() +*/ +void KDTimeHeaderWidget::setMajorScaleCount( int count ) +{ + myMajorScaleCount=count; + computeTicks(); +} + + +/*! + Returns the number of ticks per unit in the major scale. + + \return the number of ticks in the major scale + \sa setMajorScaleCount(), setMinorScaleCount(), minorScaleCount() +*/ +int KDTimeHeaderWidget::majorScaleCount() const +{ + return myMajorScaleCount; +} + + +/*! + Sets the number of ticks in the minor scale. + + \param count the number of ticks in the minor scale + \sa minorScaleCount, setMajorScaleCount, majorScaleCount() +*/ +void KDTimeHeaderWidget::setMinorScaleCount( int count ) +{ + myMinorScaleCount = count; + computeTicks(); +} + + +/*! + Returns the number of ticks per unit in the minor scale. + + \return the number of ticks in the minor scale + \sa setMinorScaleCount(), setMajorScaleCount(), majorScaleCount() +*/ +int KDTimeHeaderWidget::minorScaleCount() const +{ + return myMinorScaleCount ; + +} + + +void KDTimeHeaderWidget::resizeEvent ( QResizeEvent * ) +{ + // qDebug("KDTimeHeaderWidget:: resizeEvent "); + paintPix.resize( 800, height () ); +} + + +void KDTimeHeaderWidget::updateTimeTable() +{ + //qDebug("KDTimeHeaderWidget::updateTimeTable() "); + if (flagDoNotRecomputeAfterChange) return; + // setting the scrolling steps + int scrollLineStep = myGridMinorWidth; + if (showMajorTicks()) { + QValueList<int>::iterator intIt = majorTicks.begin(); + scrollLineStep = 5 * myGridMinorWidth; + if (intIt != majorTicks.end()) { + int left = *intIt; + ++intIt; + if (intIt != majorTicks.end()) { + scrollLineStep = *intIt-left; + } + } + } + myGanttView->myCanvasView->horizontalScrollBar()->setLineStep(scrollLineStep); + myGanttView->myTimeTable->maximumComputedGridHeight = 0; + myGanttView->myTimeTable->updateMyContent(); +} + + +void KDTimeHeaderWidget::setAutoScaleMinorTickCount( int count ) +{ + myAutoScaleMinorTickcount = count; + computeTicks(); + +} + + +int KDTimeHeaderWidget::autoScaleMinorTickCount() +{ + return myAutoScaleMinorTickcount; +} + + +void KDTimeHeaderWidget::repaintMe(int left,int paintwid, QPainter* painter) +{ + if (flagDoNotRecomputeAfterChange) return; + QColorGroup qcg =QColorGroup( white, black,white, darkGray,black,gray,gray) ; + QPainter* p; + int offsetLeft = 0; + if ( paintwid > paintPix.width()-100 ) + paintPix.resize( paintwid+100, height () ); + if ( painter ) + p = painter; + else { + p = new QPainter( &paintPix ); + offsetLeft = left-50; + } + if ( mouseDown ) { + p->fillRect( left-offsetLeft, 0, paintwid, height(), QBrush(paletteBackgroundColor()) ); + int start ; + int wid; + if ( beginMouseDown < endMouseDown ) { + start = beginMouseDown ; + wid = endMouseDown - beginMouseDown ; + } else { + start = endMouseDown ; + wid = -endMouseDown + beginMouseDown ; + } + p->fillRect( start-offsetLeft, 0, wid, height(), QBrush(paletteBackgroundColor().dark()) ); + } else { + if (! painter ) + p->fillRect( left-offsetLeft, 0, paintwid, height(), QBrush(paletteBackgroundColor()) ); + } + p->setPen(QColor(40,40,40)); + QFont tempFont = p->font(); + tempFont.setWeight(63); + p->setFont(tempFont); + int hei1 = myMajorGridHeight, + hei2 = height(), + wid1 = myGridMinorWidth; + int xCoord; + int lwid = 1; + + QValueList<QString>::iterator it; + QValueList<int>::iterator intIt = majorTicks.begin(); + for ( it = majorText.begin(); it != majorText.end(); ++it ) { + xCoord = (*intIt++); + if (((*intIt)>= left && xCoord <= left+paintwid)) { + qDrawShadeLine ( p,xCoord-offsetLeft ,hei1+1, xCoord-offsetLeft, -2, qcg, true, lwid, 1 ); + p->drawText(xCoord+4-offsetLeft,hei1-4,(*it)); + } + } + qDrawShadeLine ( p,left-offsetLeft ,hei1, left+paintwid-offsetLeft, hei1, qcg, true, lwid, 1 ); + int i = 0; + for ( it = minorText.begin(); it != minorText.end(); ++it ) { + if (i*wid1 >= left-wid1 && i*wid1 <= left+paintwid) { + qDrawShadeLine ( p,i*wid1-offsetLeft ,hei1-1, i*wid1-offsetLeft, hei2, qcg, true, lwid, 1 ); + p->drawText(i*wid1+1-offsetLeft,hei1+1,wid1-1,hei2-hei1,Qt::AlignCenter,(*it)); + } + ++i; + } + p->setPen(black); + p->drawLine(left-offsetLeft,hei1,left+paintwid-offsetLeft,hei1); + qDrawShadeLine ( p,left-offsetLeft ,hei2-1, left+paintwid-offsetLeft, hei2-1, qcg, true, lwid, 1 ); + p->drawLine(left-offsetLeft,hei2-1,left+paintwid-offsetLeft,hei2-1); + if ( !painter ) { + p->end(); + delete p; + bitBlt ( this, left, 0, &paintPix, 50, 0, paintwid, height() ); + } +} + +// cuts the secs in the DateTime if scale is Minute , +// the minutes and secs if scale is Hour and so on + +QDateTime KDTimeHeaderWidget::getEvenTimeDate(QDateTime tempdatetime ,Scale sc) +{ + QDate tempdate; + int min, hour; + int tempMinorScaleCount = myRealMinorScaleCount; + switch (sc) + { + case KDGanttView::Month: + tempdate = tempdatetime.date(); + while (tempdate.day ()!= 1 ) + tempdate = tempdate.addDays(-1); + //while (tempdate.month ()!= 1 ) + //tempdate = tempdate.addMonths(-1); + tempdatetime = QDateTime (tempdate, QTime (0,0)); + break; + case KDGanttView::Week: + tempdate = tempdatetime.date(); + while (tempdate.dayOfWeek ()!= KGlobal::locale()->weekStartDay()) + tempdate = tempdate.addDays(-1); + //tempdate = tempdate.addDays(-7); + tempdatetime = QDateTime (tempdate, QTime (0,0)); + break; + case KDGanttView::Day: + tempdatetime = QDateTime (tempdatetime.date(), QTime ( 0,0 ) ); + break; + case KDGanttView::Hour: + hour = tempdatetime.time().hour(); + while (24%tempMinorScaleCount > 0 && 24%tempMinorScaleCount < 24) + ++tempMinorScaleCount; + hour = ( hour /tempMinorScaleCount)*tempMinorScaleCount; + tempdatetime = QDateTime (tempdatetime.date(), QTime (hour, 0 )); + break; + case KDGanttView::Minute: + min = tempdatetime.time().minute(); + while (60%tempMinorScaleCount > 0 && 60%tempMinorScaleCount < 60) + ++tempMinorScaleCount; + // qDebug("myMinorScaleCount %d %d %d",myMinorScaleCount, myRealMinorScaleCount, tempMinorScaleCount); + min = (min /tempMinorScaleCount)*tempMinorScaleCount; + tempdatetime = QDateTime (tempdatetime.date(), QTime (tempdatetime.time().hour(),min )); + + break; + case KDGanttView::Auto: + break; + } + return tempdatetime; +} + + +void KDTimeHeaderWidget::computeRealScale(QDateTime start) +{ + + if (myScale ==KDGanttView::Auto) { + //qDebug("Autoscale "); + //double secsPerMinor = (((double)start.daysTo(myHorizonEnd))* 86400.00)/((double)myAutoScaleMinorTickcount); + double secsPerMinor = (((double)start.secsTo(myHorizonEnd)))/((double)myAutoScaleMinorTickcount); + secsPerMinor /= myZoomFactor; + if (secsPerMinor <= 1800) { + myRealScale = KDGanttView::Minute; + myRealMinorScaleCount = (int) secsPerMinor/60; + } else { + if (secsPerMinor <= 12*3600) { + myRealScale = KDGanttView::Hour; + myRealMinorScaleCount = (int) secsPerMinor/3600; + } else { + if (secsPerMinor <= 24*3600*3) { + myRealScale = KDGanttView::Day; + myRealMinorScaleCount = (int) secsPerMinor/(3600*24); + } else { + if (secsPerMinor <= 24*3600*14) { + myRealScale = KDGanttView::Week; + myRealMinorScaleCount = (int) secsPerMinor/(3600*24*7); + } else { + myRealScale = KDGanttView::Month; + myRealMinorScaleCount = (int) secsPerMinor/(3600*24*30); + + } + } + } + } + if(myRealMinorScaleCount == 0) + myRealMinorScaleCount = 1; + myRealMajorScaleCount = 1; + } + else { + //qDebug("Fixed scale "); + myRealScale = myScale; + if (myRealScale > myMaxScale) + myRealScale = myMaxScale; + if (myRealScale < myMinScale) + myRealScale = myMinScale; + myRealMinorScaleCount = (int) ( ((double)myMinorScaleCount) /myZoomFactor ); + double tempZoom = myZoomFactor; + myRealMajorScaleCount = myMajorScaleCount; + while (myRealMinorScaleCount == 0) { + if (myRealScale == myMinScale) { + myRealMinorScaleCount = 1; + break; + } + switch (myRealScale) + { + case KDGanttView::Minute: + myRealMinorScaleCount = 1; + return; + break; + case KDGanttView::Hour: + myRealScale = KDGanttView::Minute; + tempZoom = tempZoom/60; + break; + case KDGanttView::Day: + myRealScale = KDGanttView::Hour; + tempZoom = tempZoom/24; + break; + case KDGanttView::Week: + myRealScale = KDGanttView::Day; + tempZoom = tempZoom/7; + break; + case KDGanttView::Month: + myRealScale = KDGanttView::Week ; + tempZoom = tempZoom*7/30; + break; + case KDGanttView::Auto: + break; + } + myRealMinorScaleCount = (int) ( myMinorScaleCount /tempZoom ); + } + } +} + + +void KDTimeHeaderWidget::computeTicks(bool doNotComputeRealScale) +{ + if (flagDoNotRecomputeAfterChange) return; + bool block = myGanttView->myTimeTable->blockUpdating(); + myGanttView->myTimeTable->setBlockUpdating( true ); + //qDebug("computeticks "); + majorTicks.clear(); + minorText.clear(); + majorText.clear(); + if ( !doNotComputeRealScale ) + saveCenterDateTime(); + if (!doNotComputeRealScale) + computeRealScale(myHorizonStart); + myRealStart = getEvenTimeDate(myHorizonStart ,myRealScale); + if (!doNotComputeRealScale) + computeRealScale(myRealStart); + int tempMinorScaleCount = myRealMinorScaleCount, + tempMajorScaleCount = myRealMajorScaleCount; + int minorItems,minorPerMajor = 1; + minorItems = (int) (secsFromTo( myRealStart, myHorizonEnd)/60.0); + //qDebug("tempMinorScaleCount %d ", tempMinorScaleCount); + QPainter p(this); + int Width, Height; + QString testTextMinor,testTextMajor, tempStr; + QRect itemRectMinor, itemRectMajor; + QDate tempDate = myRealStart.date(); + myRealEnd = myRealStart; + // preparing the testtext for the differennt scales + switch (myRealScale) + { + // the x in testTextMajor is added to reserve a little bit more space + case KDGanttView::Minute: + testTextMinor = "60"; + if (myHourFormat == KDGanttView::Hour_12) + testTextMajor = "Mon Aug 30, 12 AMx"; + else + testTextMajor = "Mon Aug 30, 24:00x"; + minorPerMajor = 6000; + break; + case KDGanttView::Hour: + minorItems = minorItems/60; + if (myHourFormat == KDGanttView::Hour_24) + testTextMinor = "24x"; + else + testTextMinor = "12 AM"; + testTextMajor = "Mon Aug 30, x"; + if ( yearFormat() != KDGanttView::NoDate ) + testTextMajor += getYear(QDate::currentDate()); + minorPerMajor = 2400; + break; + case KDGanttView::Day: + minorItems = minorItems/(60*24); + testTextMinor = "88"; + testTextMajor = "Aug 30, x"+getYear(QDate::currentDate()); + minorPerMajor = 700; + break; + case KDGanttView::Week: + minorItems = minorItems/(60*24*7); + testTextMinor = "88"; + testTextMajor = "Aug x"+getYear(QDate::currentDate()); + minorPerMajor = 435; // 435 = 365days/12months/7days * 100 + break; + case KDGanttView::Month: + minorItems = (minorItems*12)/(60*24*365); + testTextMinor = "M"; + testTextMajor = "x"+getYear(QDate::currentDate()); + minorPerMajor = 1200; + break; + case KDGanttView::Auto: + qDebug("KDGanttView::Internal Error in KDTimeHeaderWidget::computeTicks() "); + qDebug(" RealScale == Auto : This may not be! "); + break; + } + itemRectMinor = p.boundingRect ( 10, 10, 2, 2, Qt::AlignLeft,testTextMinor); + itemRectMajor = p.boundingRect ( 10, 10, 2, 2, Qt::AlignLeft,testTextMajor); + p.end(); + //qDebug(" tempMinorScaleCount %d ", tempMinorScaleCount); + Height = itemRectMinor.height()+itemRectMajor.height()+11; + Width = (itemRectMinor.width()+5); + if (Width < minimumColumnWidth()) Width = minimumColumnWidth(); + // if the desired width is greater than the maximum width of this widget + // increase the minorscalecount + int maxWid = myGanttView->myCanvasView->viewport()->width(); + if (!flagZoomToFit) + maxWid = maximumWidth(); + while((minorItems/tempMinorScaleCount+1)*Width > maxWid) + ++tempMinorScaleCount; + //qDebug(" tempMinorScaleCount %d ", tempMinorScaleCount); + mySizeHint = (minorItems/tempMinorScaleCount+1)*Width; + switch (myRealScale) + { + case KDGanttView::Minute: + if (tempMinorScaleCount < 60) + while (60%tempMinorScaleCount > 0 && 60%tempMinorScaleCount < 60) + ++tempMinorScaleCount; + if (tempMinorScaleCount >= 60) { + myRealScale = KDGanttView::Hour; + myRealMinorScaleCount = tempMinorScaleCount/ 60; + // myRealMinorScaleCount = 1; + myRealMajorScaleCount = 1; + qDebug("KDGantt::Overzoom:Rescaling from Minute to Hour"); + myGanttView->myTimeTable->setBlockUpdating( block ); + emit myGanttView->rescaling( KDGanttView::Hour ); + computeTicks(true); + return; + } + break; + case KDGanttView::Hour: + while (24%tempMinorScaleCount > 0 && 24%tempMinorScaleCount < 24) + ++tempMinorScaleCount; + if (tempMinorScaleCount >= 24) { + myRealScale = KDGanttView::Day; + myRealMinorScaleCount = tempMinorScaleCount/ 24; + //myRealMinorScaleCount = 1; + myRealMajorScaleCount = 1; + qDebug("KDGantt::Overzoom:Rescaling from Hour to Day"); + myGanttView->myTimeTable->setBlockUpdating( block ); + emit myGanttView->rescaling( KDGanttView::Day ); + computeTicks(true); + return; + } + break; + default: + break; + } + //flagZoomToFit = false; + while((minorItems/tempMinorScaleCount+1)*Width < myMinimumWidth ) { + ++minorItems; + } + minorItems = (minorItems/tempMinorScaleCount)+1; + // if not enough space for the text of the major scale, increase majorscalecount + minorPerMajor = (minorPerMajor*tempMajorScaleCount)/tempMinorScaleCount; + // checking, if enough space for majorscale + // if not, increasing MajorScaleCount + + while ((minorPerMajor*Width)/100 < itemRectMajor.width()) { + minorPerMajor = minorPerMajor/tempMajorScaleCount; + ++tempMajorScaleCount; + minorPerMajor = minorPerMajor*tempMajorScaleCount; + + } + // now we have the fixed width of the minorscale computed + myGridMinorWidth = Width; + // the width of this widget is the gridwidth * the amount of items + Width *= minorItems; + // if size changed, reset geometry + if (width() != Width || height() != Height ) + { + resize( Width, Height ); + emit sizeChanged( Width ); + } + myMajorGridHeight = itemRectMajor.height()+5; + QTime tempTime = myRealStart.time(); + QDateTime tempDateTime; + int i; + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + switch (myRealScale) + { + case KDGanttView::Minute: + myRealEnd = myRealEnd.addSecs((minorItems)*tempMinorScaleCount*60); + for ( i = 0; i < minorItems;++i) { + tempStr.setNum(tempTime.minute()); + minorText.append(tempStr); + tempTime = tempTime.addSecs(60*tempMinorScaleCount); + } + tempDateTime = myRealStart; + while (tempDateTime.time().minute() != 0) + tempDateTime = tempDateTime.addSecs(60); + while (tempDateTime < myRealEnd) { + majorTicks.append( getCoordX(tempDateTime)); + tempStr.setNum(tempDateTime.date().day()); + if ( yearFormat() == KDGanttView::NoDate ) { + tempStr = calendar->weekDayName( tempDateTime.date() )+", " + +getHour(tempDateTime.time()); + } else { + tempStr = calendar->weekDayName( tempDateTime.date(), true )+" "+ + calendar->monthName( tempDateTime.date().month(), tempDateTime.date().year(), true)+ " "+ + tempStr+", "+getHour(tempDateTime.time()); + } + + majorText.append(tempStr); + tempDateTime = tempDateTime.addSecs(3600*tempMajorScaleCount); + } + majorTicks.append( getCoordX(tempDateTime)); + break; + + case KDGanttView::Hour: + myRealEnd = myRealEnd.addSecs(minorItems*tempMinorScaleCount*60*60); + + for ( i = 0; i < minorItems;++i) { + tempStr = getHour(tempTime); + minorText.append(tempStr); + tempTime = tempTime.addSecs(3600*tempMinorScaleCount); + } + tempDateTime = myRealStart; + while (tempDateTime.time().hour() != 0) + tempDateTime = tempDateTime.addSecs(3600); + while (tempDateTime < myRealEnd) { + majorTicks.append( getCoordX(tempDateTime)); + tempStr.setNum(tempDateTime.date().day()); + if ( yearFormat() == KDGanttView::NoDate ) { + tempStr = calendar->weekDayName( tempDateTime.date() ); + } else { + tempStr = calendar->weekDayName( tempDateTime.date(), true )+" "+ + calendar->monthName( tempDateTime.date().month(), tempDateTime.date().year(), true)+ " "+ + tempStr+", "+getYear(tempDateTime.date()); + } + majorText.append(tempStr); + tempDateTime = tempDateTime.addDays(tempMajorScaleCount); + } + majorTicks.append( getCoordX(tempDateTime)); + break; + case KDGanttView::Day: + myRealEnd = myRealEnd.addDays(minorItems*tempMinorScaleCount); + for ( i = 0; i < minorItems;++i) { + if (tempMinorScaleCount == 1) + minorText.append((calendar->weekDayName(tempDate, true)).left(1)); //TODO: BIDI + else + minorText.append(QString::number(tempDate.day())); + tempDate = tempDate.addDays(tempMinorScaleCount); + } + tempDate = myRealStart.date(); + while (tempDate.dayOfWeek() != KGlobal::locale()->weekStartDay()) + tempDate = tempDate.addDays(1); + while (tempDate < myRealEnd.date()) { + majorTicks.append( getCoordX(tempDate)); + tempStr.setNum(tempDate.day()); + tempStr = calendar->monthName(tempDate.month(), tempDate.year(), true)+ " "+ + tempStr+", "+getYear(tempDate); + majorText.append(tempStr); + tempDate = tempDate.addDays(7*tempMajorScaleCount); + } + majorTicks.append( getCoordX(tempDate)); + break; + case KDGanttView::Week: + myRealEnd = myRealEnd.addDays(minorItems*tempMinorScaleCount*7); + for ( i = 0; i < minorItems;++i) { + tempStr.setNum(tempDate.day()); + minorText.append(tempStr); + tempDate = tempDate.addDays(7*tempMinorScaleCount); + } + tempDate = myRealStart.date(); + while (tempDate.day() != KGlobal::locale()->weekStartDay()) + tempDate = tempDate.addDays(1); + while (tempDate < myRealEnd.date()) { + majorTicks.append( getCoordX(tempDate)); + tempStr = calendar->monthName(tempDate.month(), tempDate.year(), true)+ " "+getYear(tempDate); + majorText.append(tempStr); + tempDate = tempDate.addMonths(tempMajorScaleCount); + } + majorTicks.append( getCoordX(tempDate)); + break; + case KDGanttView::Month: + myRealEnd = myRealEnd.addMonths(minorItems*tempMinorScaleCount); + for ( i = 0; i < minorItems;++i) { + minorText.append((calendar->monthName(tempDate.month(), tempDate.year(), true)).left(1)); //TODO: BIDI + tempDate = tempDate.addMonths(tempMinorScaleCount); + } + tempDate = myRealStart.date(); + while (tempDate.month() != 1) + tempDate = tempDate.addMonths(1); + while (tempDate < myRealEnd.date()) { + majorTicks.append( getCoordX(tempDate)); + tempStr = getYear(tempDate); + majorText.append(tempStr); + tempDate = tempDate.addYears(tempMajorScaleCount); + } + majorTicks.append( getCoordX(tempDate)); + break; + case KDGanttView::Auto: + break; + } + + if (flagDoNotRepaintAfterChange) { + myGanttView->myTimeTable->setBlockUpdating( block ); + return; + } + //qDebug("KDTimeHeaderWidget width %d, viewport width %d ",width (), myGanttView->myCanvasView->viewport()->width()); + myGanttView->myTimeTable->setBlockUpdating( block ); + updateTimeTable(); + centerDateTime(myCenterDateTime); + repaint(); +} + + +void KDTimeHeaderWidget::saveCenterDateTime() +{ + double wid = width(); + double allsecs = secsFromTo( myRealStart, myRealEnd ); + double center = myGanttView->myCanvasView->viewport()->width(); + center = center / 2; + center = center + myGanttView->myCanvasView->contentsX(); + double secs = (allsecs*center)/wid; + double days = secs/86400.0; + secs = secs - ( (int) days *86400.0 ); + myCenterDateTime = (myRealStart.addDays ( (int) days )).addSecs( (int) secs); +} + + +void KDTimeHeaderWidget::centerDateTime( const QDateTime& center ) +{ + moveTimeLineTo(getCoordX( center )-(myGanttView->myCanvasView->viewport()->width() /2)); + // qDebug("centerDateTime %s %d %d", center.toString().latin1(),getCoordX( center ),(myGanttView->myCanvasView->viewport()->width() /2) ); + +} + + +void KDTimeHeaderWidget::paintEvent(QPaintEvent *p) +{ + repaintMe(p->rect().x(),p->rect().width()); +} + + +int KDTimeHeaderWidget::getCoordX(QDate date) +{ + int wid = width(); + int daysAll = myRealStart.daysTo(myRealEnd); + if (daysAll == 0) return 0; + int days = myRealStart.daysTo(QDateTime(date)); + return (wid *days) /daysAll; +} + + +int KDTimeHeaderWidget::getCoordX(QDateTime datetime) +{ + double wid = width(); + double secsAll = secsFromTo( myRealStart, myRealEnd ); + if (secsAll == 0.0) return 0; + double secs = secsFromTo( myRealStart, datetime); + return ((int)((wid *(secs /secsAll))+0.5)); +} + + +QString KDTimeHeaderWidget::getYear(QDate date) +{ + QString ret; + ret.setNum(date.year()); + switch (yearFormat()) { + case KDGanttView::FourDigit: + // nothing to do + break; + case KDGanttView::TwoDigit: + ret = ret.right(2); + break; + case KDGanttView::TwoDigitApostrophe: + ret = "'"+ret.right(2); + break; + case KDGanttView::NoDate: + // nothing to do + break; + } + return ret; +} + + +QString KDTimeHeaderWidget::getHour(QTime time) +{ + QString ret; + int hour = time.hour(); + if (myHourFormat == KDGanttView::Hour_12) { + if (hour >= 12) { + if (hour > 12) hour -=12; + ret.setNum(hour); + ret = ret +" PM"; + } else { + if (hour == 0) hour = 12; + ret.setNum(hour); + ret = ret +" AM"; + } + } else { + if (myHourFormat == KDGanttView::Hour_24) + ret.setNum(hour); + else { + ret.setNum(hour); + ret += ":00"; + } + } + return ret; +} + + +void KDTimeHeaderWidget::mousePressEvent ( QMouseEvent * e ) +{ + mouseDown = false; + switch ( e->button() ) { + case LeftButton: + mouseDown = true; + beginMouseDown = e->pos().x(); + endMouseDown = e->pos().x(); + break; + case RightButton: + if (flagShowPopupMenu) + myPopupMenu->popup(e->globalPos()); + break; + case MidButton: + break; + default: + break; + } + +} + + +void KDTimeHeaderWidget::mouseReleaseEvent ( QMouseEvent * ) +{ + if ( mouseDown ) { + mouseDown = false; + // zoom to selection getDateTimeForIndex( + int start, end; + if ( beginMouseDown < endMouseDown ) { + start = beginMouseDown; + end = endMouseDown; + } else { + start = endMouseDown; + end = beginMouseDown; + } + if (start < 0 ) + start = 0; + if ( end > width() ) + end = width(); + //qDebug("start %s ",getDateTimeForIndex(start).toString().latin1() ); + //qDebug("end %s ",getDateTimeForIndex(end).toString().latin1() ); + emit myGanttView->timeIntervalSelected( getDateTimeForIndex(start),getDateTimeForIndex(end) ); + emit myGanttView->timeIntervallSelected( getDateTimeForIndex(start),getDateTimeForIndex(end) ); + //zoomToSelection( getDateTimeForIndex(start),getDateTimeForIndex(end) ); + } + mouseDown = false; + repaint(); +} + + +void KDTimeHeaderWidget::mouseDoubleClickEvent ( QMouseEvent * ) +{ + +} + + +void KDTimeHeaderWidget::mouseMoveEvent ( QMouseEvent * e ) +{ + if ( mouseDown ) { + if ( e->pos().y() < -height() || e->pos().y() > 2* height() ) { + mouseDown = false; + repaint(); + return; + } + endMouseDown = e->pos().x(); + //repaint; + int val = -1; + if (endMouseDown < -x() ) { + val = myGanttView->myCanvasView->horizontalScrollBar()->value() - + myGanttView->myCanvasView->horizontalScrollBar()->lineStep(); + if ( val < 0 ) { + val = 0; + } + } + if (endMouseDown > -x() +parentWidget()->width() ) { + val = myGanttView->myCanvasView->horizontalScrollBar()->value() + + myGanttView->myCanvasView->horizontalScrollBar()->lineStep(); + + } + repaintMe(-x(),parentWidget()->width()); + if ( val > -1 ) { + if ( val > myGanttView->myCanvasView->horizontalScrollBar()->maxValue() ) { + val = myGanttView->myCanvasView->horizontalScrollBar()->maxValue(); + } + myGanttView->myCanvasView->horizontalScrollBar()->setValue( val ); + } + //qDebug("mousemove %d %d %d %d",endMouseDown, -x(),parentWidget()->width() , e->pos().y()); + } +} + + +/* *************************************************************** + KDLegendWidget:: KDLegendWidget + ***************************************************************** */ +KDLegendWidget:: KDLegendWidget( QWidget* parent, + KDGanttMinimizeSplitter* legendParent ) : + KDGanttSemiSizingControl ( KDGanttSemiSizingControl::Before, Vertical, + parent) +{ + myLegendParent = legendParent; + dock = 0; + scroll = new QScrollView( legendParent ); + setMaximizedWidget( scroll ); + + setMinimizedWidget( myLabel = new QLabel( i18n( " Legend is hidden" ), this) ); + setGeometry( 0, 0, 50, 50 ); + myLegend = 0; + clearLegend(); + showMe ( false ); +} +void KDLegendWidget::setAsDockwindow( bool dockwin ) +{ + if ( (dock == 0 && !dockwin) || ( dock && dockwin ) ) + return; + if ( dockwin ) + { + setMaximizedWidget( 0 ); + showMe ( false ); + if ( dock ) delete dock; + dock = new QDockWindow(QDockWindow:: OutsideDock,0 ); + dock->resize( 200, 100 ); + dock->setHorizontallyStretchable( true ); + dock->setVerticallyStretchable( true ); + dock->setCaption(i18n("Legend: ") ); + dock->setResizeEnabled (true ); + delete myLegend; + myLegend = 0; + delete scroll; + scroll = new QScrollView( dock ); + clearLegend(); + dock->setWidget(scroll); + setMaximizedWidget( dock ); + showMe ( false ); + + } else { + setMaximizedWidget( 0 ); + showMe ( false ); + delete myLegend; + myLegend = 0; + delete scroll; + delete dock; + dock = 0; + scroll = new QScrollView( myLegendParent ); + clearLegend(); + setMaximizedWidget( scroll ); + showMe ( false ); + } + +} + + +bool KDLegendWidget::asDockwindow( ) +{ + if ( dock ) + return true; + return false; +} + + +QDockWindow* KDLegendWidget::dockwindow( ) +{ + return dock; +} + + +void KDLegendWidget::setFont( QFont font) +{ + myLegend->setFont( font); + myLabel->setFont( font); + QWidget::setFont( font ); +} + + +void KDLegendWidget::drawToPainter( QPainter *p ) +{ + p->drawPixmap( 0, 0, QPixmap::grabWidget( myLegend ) ); +} + + +QSize KDLegendWidget::legendSize() +{ + return myLegend->size(); +} + + +QSize KDLegendWidget::legendSizeHint() +{ + QApplication::sendPostedEvents( 0, QEvent::LayoutHint ); + return QSize( myLegend->sizeHint().width(), myLegend->sizeHint().height()+scroll->horizontalScrollBar()->height()); +} + + +void KDLegendWidget::showMe ( bool show ) +{ + minimize( !show ); +} + + +void KDLegendWidget::clearLegend ( ) +{ + if ( myLegend ) delete myLegend; + if ( dock ) + myLegend = new QGroupBox( 1, Qt::Horizontal, scroll->viewport() ); + else + myLegend = new QGroupBox( 1, Qt::Horizontal, i18n( "Legend" ), scroll->viewport() ); + myLegend->setBackgroundColor( Qt::white ); + myLegend->setFont( font() ); + scroll->addChild( myLegend ); + scroll->setResizePolicy( QScrollView::AutoOneFit ); + myLegend->layout()->setMargin( 11 ); + myLegend->setFrameStyle( QFrame::NoFrame ); + if ( dock ) + scroll->setMaximumHeight( 32000 ); + else + scroll->setMaximumHeight( legendSizeHint().height() ); +} + + +void KDLegendWidget::addLegendItem( KDGanttViewItem::Shape shape, const QColor& shapeColor, const QString& text ) +{ + QLabel * temp; + QPixmap p = KDGanttView::getPixmap( shape, shapeColor, Qt::white, 10); + QWidget *w = new QWidget( myLegend ); + w->setBackgroundColor( Qt::white ); + QHBoxLayout *lay = new QHBoxLayout( w ,0, 6); + temp = new QLabel ( w ); + lay->addWidget( temp, 0, Qt:: AlignRight); + temp->setPixmap(p); + temp = new QLabel ( text, w ); + temp->setBackgroundColor( Qt::white ); + lay->addWidget( temp, 0, Qt:: AlignLeft); + lay->addStretch(); + if ( dock ) + scroll->setMaximumHeight( 32000 ); + else + scroll->setMaximumHeight( legendSizeHint().height() ); +} + + +bool KDLegendWidget::isShown ( ) +{ + return !isMinimized(); +} + + +KDListView::KDListView(QWidget* parent, KDGanttView* gantView):QListView (parent) +{ + myGanttView = gantView; + setAcceptDrops(true); + new KDListViewWhatsThis(viewport(),this); + setRootIsDecorated( true ); + setAllColumnsShowFocus( true ); + addColumn( i18n( "Task Name" ) ); + setSorting( -1 ); + //setVScrollBarMode (QScrollView::AlwaysOn ); + setHScrollBarMode (QScrollView::AlwaysOn ); + setDefaultRenameAction(QListView::Accept); + setColumnWidthMode ( 0,Maximum ); + _calendarMode = false; + // QObject::connect(this, SIGNAL ( pressed ( QListViewItem * )) , this, SLOT( dragItem( QListViewItem *))) ; +} + + +void KDListView::dragItem( QListViewItem * ) +{ + // qDebug("drag "); + // startDrag(); +} +QString KDListView::getWhatsThisText(QPoint p) +{ + KDGanttViewItem* item = ( KDGanttViewItem* ) itemAt( p ); + if ( item ) + return item->whatsThisText(); + return i18n( "No item Found" ); +} + +void KDListView::setCalendarMode( bool mode ) +{ + _calendarMode = mode; + // setRootIsDecorated ( ! mode ); +} + +void KDListView::setOpen(QListViewItem * item, bool open ) +{ + if (! _calendarMode || ! open ) { + (( KDGanttViewItem*)item)->setCallListViewOnSetOpen( false ); + QListView::setOpen ( item, open ); + (( KDGanttViewItem*)item)->setCallListViewOnSetOpen( true ); + return; + } + // we are in calendarmode + // in calendarmode only items can be opened which have subitems which have subitems + + QListViewItem* temp; + temp = item->firstChild(); + bool openItem = false; + while (temp) { + if ( (( KDGanttViewItem*)temp)->displaySubitemsAsGroup() ) { + temp->setVisible( true ); + openItem = true; + } + else { + temp->setVisible( false ); + //qDebug(" temp->setVisible( false );"); + } + temp = temp->nextSibling(); + } + if ( openItem ) { + (( KDGanttViewItem*)item)->setCallListViewOnSetOpen( false ); + QListView::setOpen ( item, open ); + (( KDGanttViewItem*)item)->setCallListViewOnSetOpen( true ); + } +} + + +void KDListView::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + QListView::contentsMouseDoubleClickEvent ( e ); + //if ( ! _calendarMode ) + // QListView::contentsMouseDoubleClickEvent ( e ); + // else + { + + emit myGanttView->lvItemDoubleClicked ( (KDGanttViewItem*) itemAt(e->pos() ) ); + emit myGanttView->itemDoubleClicked ( (KDGanttViewItem*) itemAt(e->pos() ) ); + } + +} + + +void KDListView::drawToPainter ( QPainter * p, bool drawHeader ) +{ + // Draw list + drawAllContents ( p, 0, 0, contentsWidth(), contentsHeight() ); + if (!drawHeader) { + return; + } + // Draw headers + QPen pen = QPen(Qt::lightGray, 1); + p->save(); + QHeader *h = header(); + for (int s = 0; s < h->count(); ++s) { + QRect r = h->sectionRect(s); + if (s==0) { + p->translate(0, -r.height()); + } + //kdDebug()<<s<<": "<<h->label(s)<<" "<<r<<endl; + p->drawText(r.x()+2, r.y(), r.width()-2, r.height(), columnAlignment(s)|Qt::AlignVCenter, h->label(s), -1); + p->save(); + p->setPen(pen); + p->drawRect(r.x(), r.y()+1, r.width(), r.height()-2); + p->restore(); + + } + p->restore(); +} + +int KDListView::buildDrawables(QPtrList<KDListView::DrawableItem> &lst, int level, int ypos, QListViewItem *item, int ymin, int ymax) const { + int y = ypos; + int ih = item->height(); + if (y < ymin && y+ih > ymin) { + y = ymin; // include partial item at top + } + if (y >= ymin && y < ymax) { // include partial item at bottom + KDListView::DrawableItem *dr = new KDListView::DrawableItem(level, y, item); + lst.append(dr); + //kdDebug()<<k_funcinfo<<level<<", "<<y<<" : "<<item->text(0)<<endl; + } + y += ih; + if (item->isOpen()) { + QListViewItem *child = item->firstChild(); + for (; child; child = child->nextSibling()) { + y = buildDrawables(lst, level+1, y, child, ymin, ymax); + } + } + return y; +} +// This is a copy of QListView::drawContentsOffset(), with a few changes +// because drawContentsOffset() only draws *visible* items, +// we want to draw *all* items. +// FIXME: Haven't got paintBraches() to work, atm live without it. +void KDListView::drawAllContents(QPainter * p, int cx, int cy, int cw, int ch) { + if ( columns() == 0 ) { + paintEmptyArea( p, QRect( cx, cy, cw, ch ) ); + return; + } + //kdDebug()<<k_funcinfo<<QRect(cx, cy, cw, ch)<<endl; + QPtrList<KDListView::DrawableItem> drawables; + drawables.setAutoDelete(true); + QListViewItem *child = firstChild(); + int level = 0; + int ypos = 0; + for (; child; child = child->nextSibling()) { + ypos = buildDrawables(drawables, level, ypos, child, cy, cy+ch); + } + + p->setFont( font() ); + + QPtrListIterator<KDListView::DrawableItem> it(drawables); + + QRect r; + int fx = -1, x, fc = 0, lc = 0; + int tx = -1; + KDListView::DrawableItem * current; + + while ( (current = it.current()) != 0 ) { + ++it; + int ih = current->i->height(); + int ith = current->i->totalHeight(); + int c; + int cs; + + // need to paint current? + if ( ih > 0 && current->y < cy+ch && current->y+ih > cy ) { + //kdDebug()<<k_funcinfo<<"Paint: "<<current->i->text(0)<<" y="<<current->y<<endl; + if ( fx < 0 ) { + // find first interesting column, once + x = 0; + c = 0; + cs = header()->cellSize( 0 ); + while ( x + cs <= cx && c < header()->count() ) { + x += cs; + c++; + if ( c < header()->count() ) + cs = header()->cellSize( c ); + } + fx = x; + fc = c; + while( x < cx + cw && c < header()->count() ) { + x += cs; + c++; + if ( c < header()->count() ) + cs = header()->cellSize( c ); + } + lc = c; + } + + x = fx; + c = fc; + // draw to last interesting column + + const QColorGroup &cg = ( palette().inactive() ); + + while ( c < lc && !drawables.isEmpty() ) { + int i = header()->mapToLogical( c ); + cs = header()->cellSize( c ); + r.setRect( x, current->y-cy, cs, ih ); + if ( i == 0 ) + r.setLeft( r.left() + current->l * treeStepSize() ); + + p->save(); + // No need to paint if the cell isn't technically visible + if ( !( r.width() == 0 || r.height() == 0 ) ) { + p->translate( r.left(), r.top() ); + int ac = header()->mapToLogical( c ); + // map to Left currently. This should change once we + // can really reverse the listview. + int align = columnAlignment( ac ); + if ( align == AlignAuto ) align = AlignLeft; + bool sel = current->i->isSelected(); + if (sel) + current->i->setSelected(false); + current->i->paintCell( p, cg, ac, r.width(), align ); + if (sel) + current->i->setSelected(sel); + } + p->restore(); + x += cs; + c++; + } + + } + + const int cell = header()->mapToActual( 0 ); + + if ( tx < 0 ) + tx = header()->cellPos( cell ); + + // do any children of current need to be painted? +/* FIXME: painting branches doesn't work for some reason... + if ( ih != ith && + rootIsDecorated() && + current->y + ith > cy && + current->y + ih < cy + ch && + tx + current->l * treeStepSize() < cx + cw && + tx + (current->l+1) * treeStepSize() > cx ) { + // compute the clip rectangle the safe way + + int rtop = current->y + ih; + int rbottom = current->y + ith; + int rleft = tx + current->l*treeStepSize(); + int rright = rleft + treeStepSize(); + + int crtop = QMAX( rtop, cy ); + int crbottom = QMIN( rbottom, cy+ch ); + int crleft = QMAX( rleft, cx ); + int crright = QMIN( rright, cx+cw ); + + r.setRect( crleft, crtop, + crright-crleft, crbottom-crtop ); + + if ( r.isValid() ) { + p->save(); + p->translate( rleft, crtop ); + //kdDebug()<<k_funcinfo<<"paintBranches: "<<current->i->text(0)<<endl; + + current->i->paintBranches( p, colorGroup(), treeStepSize(), + rtop - crtop, r.height() ); + p->restore(); + } + }*/ + } +} + +void KDListView::resizeEvent(QResizeEvent *) +{ + triggerUpdate (); +} +void KDListView::dragEnterEvent ( QDragEnterEvent * e) +{ + if ( !myGanttView->dropEnabled() ) { + e->accept( false ); + return; + } + myGanttView->lvDragEnterEvent(e); + //e->accept(KDGanttViewItemDrag::canDecode(e) ); +} + +void KDListView::dragMoveEvent ( QDragMoveEvent * e) +{ + if ( !myGanttView->dropEnabled() ) { + e->accept( false ); + return; + } + KDGanttViewItem* draggedItem = 0; + KDGanttViewItem* gItem = (KDGanttViewItem*)itemAt( e->pos()) ; + setCurrentItem( gItem ); + if ( e->source() == myGanttView ) + draggedItem = myGanttView->myCanvasView->lastClickedItem; + // execute user defined dragMoveEvent handling + if (myGanttView->lvDragMoveEvent ( e , draggedItem, gItem ) ) + return; + if ( !KDGanttViewItemDrag::canDecode(e) ) { + e->accept( false ); + return; + } + if ( e->source() == myGanttView && gItem ){ + // internal drag - do not allow to drag the item to a subitem of itself + KDGanttViewItem* pItem = gItem->parent(); + while ( pItem ) { + if ( pItem == myGanttView->myCanvasView->lastClickedItem ) { + e->accept( false ); + return; + } + pItem = pItem->parent(); + } + if ( gItem == myGanttView->myCanvasView->lastClickedItem ) { + e->accept( false ); + return; + } + } + e->accept( true ); +} + +void KDListView::dragLeaveEvent ( QDragLeaveEvent * ) +{ + //qDebug("contentsDragLeaveEvent "); +} +void KDListView::dropEvent ( QDropEvent *e ) +{ + if ( !myGanttView->dropEnabled() ) { + e->accept( false ); + return; + } + KDGanttViewItem* gItem = (KDGanttViewItem*)itemAt( e->pos()) ; + KDGanttViewItem* draggedItem = 0; + if ( e->source() == myGanttView ) + draggedItem = myGanttView->myCanvasView->lastClickedItem; + if (myGanttView->lvDropEvent ( e, draggedItem, gItem )) + return; + QString string; + KDGanttViewItemDrag::decode( e, string ); + KDGanttViewItem* newItem = 0; + + if ( gItem == myGanttView->myCanvasView->lastClickedItem && gItem != 0 ) { + qDebug("KDGanttView::Possible bug in drag&drop code "); + return; + } + + QDomDocument doc( "GanttView" ); + doc.setContent( string ); + QDomElement docRoot = doc.documentElement(); // ChartParams element + QDomNode node = docRoot.firstChild(); + bool enable = myGanttView->myTimeTable->blockUpdating( ); + myGanttView->myTimeTable->setBlockUpdating( true ); + while( !node.isNull() ) { + QDomElement element = node.toElement(); + if( !element.isNull() ) { // was really an element + QString tagName = element.tagName(); + if( tagName == "Items" ) { + QDomNode node = element.firstChild(); + while( !node.isNull() ) { + QDomElement element = node.toElement(); + if( !element.isNull() ) { // was really an element + QString tagName = element.tagName(); + if( tagName == "Item" ) { + if ( gItem ) + newItem = KDGanttViewItem::createFromDomElement( gItem, + element ); + else + newItem = KDGanttViewItem::createFromDomElement( myGanttView, + element ); + } else { + qDebug( "Unrecognized tag name: %s", tagName.latin1() ); + Q_ASSERT( false ); + } + } + //qDebug("next node1 "); + node = node.nextSibling(); + } + } + } + //qDebug("next node2 "); + node = node.nextSibling(); + } + newItem->setDisplaySubitemsAsGroup(myGanttView->displaySubitemsAsGroup()); + newItem->resetSubitemVisibility(); + myGanttView->slot_lvDropped(e, draggedItem, gItem); + myGanttView->myTimeTable->setBlockUpdating( enable ); + myGanttView->myTimeTable->updateMyContent(); + return; +} + +QDragObject * KDListView::dragObject () +{ + return QListView::dragObject (); +} + +void KDListView::startDrag () +{ + if ( ! myGanttView->dragEnabled() ) + return; + KDGanttViewItem* cItem = (KDGanttViewItem*) currentItem (); + myGanttView->myCanvasView->lastClickedItem = cItem; + myGanttView->lvStartDrag (cItem); +} + +KDCanvasText::KDCanvasText( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasText(canvas) +{ + myParentType = type; + myParentItem = parentItem; +} + + +KDCanvasLine::KDCanvasLine( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasLine(canvas) +{ + myParentType = type; + myParentItem = parentItem; +} + + +KDCanvasPolygonItem::KDCanvasPolygonItem( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasPolygonalItem( canvas ) +{ + myParentType = type; + myParentItem = parentItem; +} + + +KDCanvasPolygon::KDCanvasPolygon( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasPolygon( canvas ) +{ + myParentType = type; + myParentItem = parentItem; +} + + +KDCanvasEllipse::KDCanvasEllipse( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasEllipse( canvas ) +{ + myParentType = type; + myParentItem = parentItem; +} + + +KDCanvasRectangle::KDCanvasRectangle( KDTimeTableWidget* canvas, + void* parentItem, + int type ) : + QCanvasRectangle( canvas ) +{ + myParentType = type; + myParentItem = parentItem; +} + + + + +KDGanttCanvasView::KDGanttCanvasView( KDGanttView* sender,QCanvas* canvas, QWidget* parent, const + char* name ) : QCanvasView ( canvas, parent, name ), + movingGVItem( 0 ), + scrollBarTimer( 0, "scrollBarTimer" ) +{ + setHScrollBarMode (QScrollView::AlwaysOn ); + setVScrollBarMode( QScrollView::AlwaysOn ); + myToolTip = new KDCanvasToolTip(viewport(),this); + mySignalSender = sender; + currentItem = 0; + currentLink = 0; + cuttedItem = 0; + fromItem = 0; + fromArea = 0; + linkItemsEnabled = false; + mouseDown = false; + linkLine = new QCanvasLine(canvas); + linkLine->hide(); + linkLine->setZ(1000); + set_Mouse_Tracking(true); // mouse cursor changes over KDIntervalColorRectangle borders + new KDCanvasWhatsThis(viewport(),this); + onItem = new QPopupMenu( this ); + QPopupMenu * newMenu = new QPopupMenu( this ); + QPopupMenu * onView = new QPopupMenu( this ); + onView->insertItem( i18n( "Summary" ), this, + SLOT ( newRootItem( int ) ), 0, 0 ); + onView->insertItem( i18n( "Event" ), this, + SLOT ( newRootItem( int ) ), 0, 1); + onView->insertItem( i18n( "Task" ), this, + SLOT ( newRootItem( int ) ), 0, 2 ); + + onItem->insertItem( i18n( "New Root" ), onView ); + newMenu->insertItem( i18n( "Summary" ), + this, SLOT ( newChildItem( int) ), 0, 0 ); + newMenu->insertItem( i18n( "Event" ), + this, SLOT ( newChildItem( int ) ), 0, 1 ); + newMenu->insertItem( i18n( "Task" ), + this, SLOT ( newChildItem( int ) ), 0, 2 ); + + onItem->insertItem( i18n( "New Child" ), newMenu ); + QPopupMenu * afterMenu = new QPopupMenu( this ); + afterMenu->insertItem( i18n( "Summary" ), + this, SLOT ( newChildItem( int) ), 0, 0+4 ); + afterMenu->insertItem( i18n( "Event" ), + this, SLOT ( newChildItem( int ) ), 0, 1+4 ); + afterMenu->insertItem( i18n( "Task" ), + this, SLOT ( newChildItem( int ) ), 0, 2+4 ); + onItem->insertItem( i18n( "New After" ), afterMenu ); + QPopupMenu *pasteMenu = new QPopupMenu( this ); + pasteMenu->insertItem( i18n( "As Root" ), + this, SLOT ( pasteItem( int ) ), 0, 0 ); + pasteMenu->insertItem( i18n( "As Child" ), + this, SLOT ( pasteItem( int ) ), 0, 1 ); + pasteMenu->insertItem( i18n( "After" ), + this, SLOT ( pasteItem( int ) ), 0, 2 ); + onItem->insertItem( i18n( "Paste" ), pasteMenu, 3 ); + onItem->insertItem( i18n( "Cut Item" ), this, SLOT ( cutItem() ) ); + onItem->setItemEnabled( 3, false ); + myMyContentsHeight = 0; + _showItemAddPopupMenu = false; + + QObject *scrollViewTimer = child( "scrollview scrollbar timer", "QTimer", false ); + Q_ASSERT( scrollViewTimer ); + if ( scrollViewTimer ) { + disconnect( scrollViewTimer, SIGNAL(timeout()), this, SLOT(updateScrollBars() ) ); + } + // If they needed a scrollbar timer in scrollview... + connect( &scrollBarTimer, SIGNAL(timeout()), this, SLOT(myUpdateScrollBars() ) ); + + myScrollTimer = new QTimer( this, "myScrollTimer" ); + connect( myScrollTimer, SIGNAL( timeout() ), SLOT( slotScrollTimer() ) ); + autoScrollEnabled = false; +} + + +KDGanttCanvasView::~KDGanttCanvasView() +{ + delete myToolTip; +} + + +void KDGanttCanvasView::setShowPopupMenu( bool show ) +{ + _showItemAddPopupMenu = show; +} +bool KDGanttCanvasView::showPopupMenu() +{ + return _showItemAddPopupMenu; +} + + +void KDGanttCanvasView::moveMyContent( int, int y) +{ + setContentsPos(contentsX(), y); +} + +void KDGanttCanvasView::resizeEvent ( QResizeEvent * e ) +{ + int ho = e->oldSize().height(); + int wo = e->oldSize().width(); + int hi = height(); + int wi = width(); + //QScrollView::blockSignals( true ); + + verticalScrollBar()->setUpdatesEnabled( false ); + QScrollView::resizeEvent ( e ) ; + if ( ho != hi ) + emit heightResized( viewport()->height()); + if ( wo != wi ) + emit widthResized( viewport()->width() ); + //setMyContentsHeight( 0 ); // via timer + //QScrollView::blockSignals( false ); + scrollBarTimer.start(0, true); +} + +void KDGanttCanvasView::myUpdateScrollBars() +{ + setMyContentsHeight( 0 ); +} +void KDGanttCanvasView::setMyContentsHeight( int hei ) +{ + //qDebug("setMyContentsHeight %d %d ", hei, myMyContentsHeight); + if ( hei > 0 ) + myMyContentsHeight = hei; + verticalScrollBar()->setUpdatesEnabled( true ); // set false in resizeEvent() + if ( viewport()->height() <= myMyContentsHeight ) + verticalScrollBar()->setRange( 0, myMyContentsHeight- viewport()->height()+1); + else + verticalScrollBar()->setRange( 0,0 ); + // testing for unmatching ScrollBar values of timeheader and timetable + // may happen after external resizing + if ( horizontalScrollBar()->value() != mySignalSender->myTimeHeaderScroll->horizontalScrollBar()->value() ) { + // I am the Boss! + mySignalSender->myTimeHeaderScroll->horizontalScrollBar()->setValue(horizontalScrollBar()->value() ); + + } + +} + +// Call after *internal* resizing (like addTickRight()) +// Then the new scrollbar maxValue is in myTimeHeader. +void KDGanttCanvasView::updateHorScrollBar() { + //qDebug("horizontalScrollBar max=%d, myTimeHeaderScroll=%d", horizontalScrollBar()->maxValue(), mySignalSender->myTimeHeaderScroll->horizontalScrollBar()->value()); + + horizontalScrollBar()->setRange(mySignalSender->myTimeHeaderScroll->horizontalScrollBar()->minValue(), mySignalSender->myTimeHeaderScroll->horizontalScrollBar()->maxValue()); + +} + +void KDGanttCanvasView::cutItem( KDGanttViewItem* item ) +{ + lastClickedItem = item; + cutItem(); +} +void KDGanttCanvasView::insertItemAsRoot( KDGanttViewItem* item ) +{ + mySignalSender->myListView->insertItem( item ); + if ( item == cuttedItem ) + cuttedItem = 0; +} +void KDGanttCanvasView::insertItemAsChild( KDGanttViewItem* parent, KDGanttViewItem* item ) +{ + parent->insertItem( cuttedItem ); + if ( item == cuttedItem ) + cuttedItem = 0; +} +void KDGanttCanvasView::insertItemAfter( KDGanttViewItem* parent , KDGanttViewItem* item ) +{ + if ( parent->parent() ) { + parent->parent()->insertItem( item ); + } + else + mySignalSender->myListView->insertItem( item ); + item->moveItem( parent ); + if ( item == cuttedItem ) + cuttedItem = 0; +} + +void KDGanttCanvasView::cutItem() +{ + lastClickedItem->hideSubtree(); + //qDebug("last clicked %d parent %d ", lastClickedItem , lastClickedItem->parent()); + if ( lastClickedItem->parent() ) + lastClickedItem->parent()->takeItem(lastClickedItem); + else + mySignalSender->myListView->takeItem( lastClickedItem ); + mySignalSender->myTimeTable->updateMyContent(); + if ( cuttedItem ) + delete cuttedItem; + cuttedItem = lastClickedItem; + onItem->setItemEnabled( 3, true ); + +} +// called from the destructor in KDGanttViewItem or KDGanttView + +void KDGanttCanvasView::resetCutPaste( KDGanttViewItem* item ) +{ + if ( item == 0 && cuttedItem ) { + delete cuttedItem; + cuttedItem = 0; + } + if (item == cuttedItem) { + onItem->setItemEnabled( 3, false ); + cuttedItem = 0; + } +} + +void KDGanttCanvasView::pasteItem( int type ) +{ + if ( !cuttedItem ) + return; + switch( type ) { + case 0://root + mySignalSender->myListView->insertItem( cuttedItem ); + break; + case 1://child + lastClickedItem->insertItem( cuttedItem ); + break; + case 2://after + if ( lastClickedItem->parent() ) { + lastClickedItem->parent()->insertItem( cuttedItem ); + } + else + mySignalSender->myListView->insertItem( cuttedItem ); + cuttedItem->moveItem( lastClickedItem ); + break; + default: + ; + } + cuttedItem = 0; + onItem->setItemEnabled( 3, false ); + mySignalSender->myTimeTable->updateMyContent(); +} +void KDGanttCanvasView::newRootItem(int type) +{ + KDGanttViewItem* temp = 0; + switch( type ) { + case 1: + temp = new KDGanttViewEventItem( mySignalSender, i18n( "New Event" ) ); + break; + case 0: + temp = new KDGanttViewSummaryItem( mySignalSender, i18n( "New Summary" ) ); + break; + case 2: + temp = new KDGanttViewTaskItem( mySignalSender, i18n( "New Task" ) ); + break; + default: + ; + } + if ( temp ) + mySignalSender->editItem( temp ); +} + +void KDGanttCanvasView::newChildItem( int type ) +{ + KDGanttViewItem* temp = 0; + switch( type ) { + case 1: + temp = new KDGanttViewEventItem( lastClickedItem, i18n( "New Event" ) ); + break; + case 0: + temp = new KDGanttViewSummaryItem( lastClickedItem, i18n( "New Summary" ) ); + break; + case 2: + temp = new KDGanttViewTaskItem( lastClickedItem, i18n( "New Task" ) ); + break; + case 5: + if ( lastClickedItem->parent() ) + temp = new KDGanttViewEventItem( lastClickedItem->parent(), lastClickedItem, i18n( "New Event" ) ); + else + temp = new KDGanttViewEventItem( mySignalSender, lastClickedItem, i18n( "New Event" ) ); + break; + case 4: + if ( lastClickedItem->parent() ) + temp = new KDGanttViewSummaryItem( lastClickedItem->parent(), lastClickedItem, i18n( "New Summary" ) ); + else + temp = new KDGanttViewSummaryItem( mySignalSender, lastClickedItem, i18n( "New Summary" ) ); + break; + case 6: + if ( lastClickedItem->parent() ) + temp = new KDGanttViewTaskItem( lastClickedItem->parent(), lastClickedItem, i18n( "New Task" ) ); + else + temp = new KDGanttViewTaskItem( mySignalSender, lastClickedItem, i18n( "New Task" ) ); + break; + + + default: + ; + } + if ( temp ) + mySignalSender->editItem( temp ); +} + +void KDGanttCanvasView::drawToPainter ( QPainter * p ) +{ + drawContents ( p, 0, 0, canvas()->width(), canvas()->height() ); +} +QString KDGanttCanvasView::getToolTipText(QPoint p) +{ + QCanvasItemList il = canvas()->collisions ( viewportToContents( p )); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + return (getItem(*it))->tooltipText(); + break; + case Type_is_KDGanttTaskLink: + return (getLink(*it))->tooltipText(); + break; + default: + break; + } + } + return ""; +} + +QString KDGanttCanvasView::getWhatsThisText(QPoint p) +{ + QCanvasItemList il = canvas() ->collisions (viewportToContents( p )); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + return (getItem(*it))->whatsThisText(); + break; + case Type_is_KDGanttTaskLink: + return (getLink(*it))->whatsThisText(); + break; + default: + break; + } + } + return ""; +} + + +KDGanttCanvasView::MovingOperation KDGanttCanvasView::gvItemHitTest( KDGanttViewItem *item, KDTimeHeaderWidget* timeHeader, const QPoint &pos ) +{ + const int left = timeHeader->getCoordX( item->startTime() ); + const int right = timeHeader->getCoordX( item->endTime() ); + const int width = right - left + 1; + const int x = pos.x(); + if ( x < left + width / 10 ) + return KDGanttCanvasView::ResizingLeft; + if ( x > right - width / 10 ) + return KDGanttCanvasView::ResizingRight; + return KDGanttCanvasView::Moving; +} + +/** + Handles the mouseevent if a mousekey is pressed + + \param e the mouseevent + +*/ + +void KDGanttCanvasView::contentsMousePressEvent ( QMouseEvent * e ) +{ + //qDebug("mousepress! %d ", this); + //qDebug("focus %d ",qApp->focusWidget()); + setFocus(); + currentLink = 0; + currentItem = 0; + movingItem = 0; + mouseDown = true; + if (e->button() == RightButton && mySignalSender->editable()) { + lastClickedItem = (KDGanttViewItem*) mySignalSender->myListView->itemAt( QPoint(2,e->pos().y())); + if ( lastClickedItem ) { + if ( lastClickedItem->displaySubitemsAsGroup() && ! lastClickedItem->isOpen() ) { + // findSub subitem + QCanvasItemList il = canvas() ->collisions ( e->pos() ); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + if ( getType(*it) == Type_is_KDGanttViewItem ) { + lastClickedItem = getItem(*it); + } + } + } + if ( _showItemAddPopupMenu ) + onItem->popup(e->globalPos()); + } + } + QCanvasItemList il = canvas() ->collisions ( e->pos() ); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + switch ( e->button() ) { + case LeftButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + currentItem = getItem(*it); + if (! currentItem->enabled() ) { + currentItem = 0; + } else if (linkItemsEnabled && + !currentItem->isMyTextCanvas(*it)) { + fromArea = getItemArea(currentItem, e->pos().x()); + if (fromArea > 0) { + fromItem = currentItem; + linkLine->setPoints(e->pos().x(), e->pos().y(), e->pos().x(), e->pos().y()); + linkLine->show(); + } + } + { + KDCanvasRectangle *rect = dynamic_cast<KDCanvasRectangle*>( *it ); + if ( rect ) { + movingGVItem = dynamic_cast<KDGanttViewTaskItem*>( getItem( rect ) ); + if ( movingGVItem ) { + movingStart = e->pos(); + movingStartDate = movingGVItem->startTime(); + movingOperation = gvItemHitTest( movingGVItem, mySignalSender->myTimeHeader, e->pos() ); + if ( movingOperation == Moving && !movingGVItem->isMoveable() ) + movingGVItem = 0; + else if ( movingOperation != Moving && !movingGVItem->isResizeable() ) + movingOperation = Moving; + } else { + movingGVItem = 0; + } + } + } + break; + case Type_is_KDGanttTaskLink: + currentLink = getLink(*it); + break; + case Type_is_KDGanttGridItem: + if ( (*it)->rtti() == KDIntervalColorRectangle::RTTI ) { + // Cleaner would be isMovable()/isResizeable() in an interface + // implemented by all movable objects... + movingItem = static_cast<QCanvasRectangle *>(*it); + movingStart = e->pos(); + KDIntervalColorRectangle* icr = static_cast<KDIntervalColorRectangle *>( movingItem ); + KDIntervalColorRectangle::HitTest hitTest = icr->hitTest( mySignalSender->myTimeHeader, movingStart ); + movingOperation = hitTest == KDIntervalColorRectangle::Start ? ResizingLeft : + hitTest == KDIntervalColorRectangle::End ? ResizingRight : + Moving; + } + break; + default: + break; + } + break; + case RightButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + currentItem = getItem(*it); + if (! currentItem->enabled() ) + currentItem = 0; + break; + case Type_is_KDGanttTaskLink: + currentLink = getLink(*it); + break; + } + break; + case MidButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + currentItem = getItem(*it); + if (! currentItem->enabled() ) + currentItem = 0; + break; + case Type_is_KDGanttTaskLink: + currentLink = getLink(*it); + break; + } + break; + default: + break; + } + } + if (e->button() == RightButton ) { + mySignalSender->gvContextMenuRequested( currentItem, e->globalPos() ); + } + if (autoScrollEnabled && e->button() == LeftButton) { + myScrollTimer->start(50); + } +} +/** + Handles the mouseevent if a mousekey is released + + \param e the mouseevent + +*/ + +void KDGanttCanvasView::contentsMouseReleaseEvent ( QMouseEvent * e ) +{ + mouseDown = false; + static KDGanttViewItem* lastClicked = 0; + mySignalSender->gvMouseButtonClicked( e->button(), currentItem , e->globalPos() ); + //qDebug("datetime %s ",mySignalSender->getDateTimeForCoordX(e->globalPos().x(), true ).toString().latin1() ); + //qDebug("mousepos %d %d ",e->pos().x(),e->pos().y() ); + //qDebug("mouseup "); + // if ( currentLink || currentItem ) + { + switch ( e->button() ) { + case LeftButton: + myScrollTimer->stop(); + { + mySignalSender->itemLeftClicked( currentItem ); + mySignalSender->gvItemLeftClicked( currentItem ); + } + if ( currentLink ) + mySignalSender->taskLinkLeftClicked( currentLink ); + if (linkItemsEnabled && fromItem) { + linkLine->hide(); + canvas()->update(); + QCanvasItemList il = canvas() ->collisions ( e->pos() ); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + if (getType(*it) == Type_is_KDGanttViewItem) { + KDGanttViewItem *toItem = getItem(*it); + if (!toItem->isMyTextCanvas(*it)) { + int toArea = getItemArea(toItem, e->pos().x()); + if (toArea > 0 && toItem && fromItem != toItem) { + mySignalSender->linkItems(fromItem, toItem, getLinkType(fromArea, toArea)); + } + } + break; + } + } + } + fromItem = 0; + if ( movingGVItem ) { + mySignalSender->gvItemMoved( movingGVItem ); + movingGVItem = 0; + } + break; + case RightButton: + { + mySignalSender->itemRightClicked( currentItem ); + mySignalSender->gvItemRightClicked( currentItem ); + + } + if ( currentLink ) + mySignalSender->taskLinkRightClicked( currentLink ); + break; + case MidButton: + { + mySignalSender->itemMidClicked( currentItem ); + mySignalSender->gvItemMidClicked( currentItem ); + } + if ( currentLink ) + mySignalSender->taskLinkRightClicked( currentLink ); + break; + default: + break; + } + } + if ( lastClicked != currentItem ) + mySignalSender->gvCurrentChanged( currentItem ); + lastClicked = currentItem; + currentLink = 0; + currentItem = 0; +} +/** + Handles the mouseevent if a mousekey is doubleclicked + + \param e the mouseevent + +*/ + +void KDGanttCanvasView::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + QCanvasItemList il = canvas() ->collisions ( e->pos() ); + + if ( il.isEmpty() && e->button() == LeftButton ) { + //not directly sending a signal here (encapsulation and whatnot) + mySignalSender->emptySpaceDoubleClicked(e); + return; + } + + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + switch ( e->button() ) { + case LeftButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + if ( getItem(*it)->enabled() ) + mySignalSender->itemDoubleClicked(getItem(*it)); + mySignalSender->gvItemDoubleClicked(getItem(*it)); + return; + break; + case Type_is_KDGanttTaskLink: + mySignalSender->taskLinkDoubleClicked(getLink(*it)); + return; + break; + default: + break; + } + break; + /* + case RightButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + mySignalSender->itemRightClicked(getItem(*it)); + return; + break; + case Type_is_KDGanttTaskLink: + mySignalSender->taskLinkRightClicked(getLink(*it)); + return; + break; + } + break; + case MidButton: + switch (getType(*it)) { + case Type_is_KDGanttViewItem: + mySignalSender->itemMidClicked(getItem(*it)); + return; + break; + case Type_is_KDGanttTaskLink: + mySignalSender->taskLinkMidClicked(getLink(*it)); + return; + break; + } + break; + */ + default: + break; + } + } +} +/** + Handles the mouseevent if a mouse button is pressed an the mouse is moved + + \param e the mouseevent + +*/ + +void KDGanttCanvasView::contentsMouseMoveEvent ( QMouseEvent *e ) +{ + if ( !mouseDown ) { + // Update cursor + bool found = false; + QCanvasItemList il = canvas() ->collisions ( e->pos() ); + QCanvasItemList::Iterator it; + for ( it = il.begin(); it != il.end(); ++it ) { + if ( (*it)->rtti() == KDIntervalColorRectangle::RTTI ) { + found = true; + KDIntervalColorRectangle* icr = static_cast<KDIntervalColorRectangle *>( *it ); + KDIntervalColorRectangle::HitTest hitTest = icr->hitTest( mySignalSender->myTimeHeader, e->pos() ); + switch ( hitTest ) { + case KDIntervalColorRectangle::Start: + case KDIntervalColorRectangle::End: + setCursor( splitHCursor ); + break; + default: + unsetCursor(); + } + } + KDGanttViewItem *gvItem = getItem( *it ); + if ( dynamic_cast<KDGanttViewTaskItem*>( gvItem ) ) { + found = true; + MovingOperation op = gvItemHitTest( gvItem, mySignalSender->myTimeHeader, e->pos() ); + switch ( op ) { + case ResizingLeft: + case ResizingRight: + if ( gvItem->isResizeable() ) + setCursor( splitHCursor ); + break; + default: + unsetCursor(); + } + } + } + if ( !found ) + unsetCursor(); + return; + } + + const QPoint p = e->pos(); + if ( movingItem ) { + int x = qRound( movingItem->x() ); + int width = movingItem->width(); + switch( movingOperation ) { + case Moving: + x += p.x() - movingStart.x(); + break; + case ResizingLeft: { + width = qRound( movingItem->x() + movingItem->width() - p.x() ); + x = p.x(); + break; + } + case ResizingRight: + width = p.x() - x; + break; + } + movingStart = p; + if ( movingItem->rtti() == KDIntervalColorRectangle::RTTI ) { + KDIntervalColorRectangle* icr = static_cast<KDIntervalColorRectangle *>(movingItem); + const QDateTime newStart = mySignalSender->myTimeHeader->getDateTimeForIndex(x); + const QDateTime newEnd = mySignalSender->myTimeHeader->getDateTimeForIndex(x + width); + icr->setDateTimes( newStart, newEnd ); + emit mySignalSender->intervalColorRectangleMoved( newStart, newEnd ); + mySignalSender->myTimeHeader->computeIntervals( movingItem->height() ); + } + canvas()->update(); + } + + if ( movingGVItem ) { + int dx = movingStart.x() - e->pos().x(); + int x = movingGVItem->middleLeft().x() - dx; + QDateTime dt = mySignalSender->getDateTimeForCoordX( x, false ); + int duration = movingGVItem->startTime().secsTo( movingGVItem->endTime() ); + if ( movingOperation == Moving ) { + movingGVItem->setStartTime( dt ); + movingGVItem->setEndTime( dt.addSecs( duration ) ); + } else if ( movingOperation == ResizingLeft ) { + movingGVItem->setStartTime( dt ); + } else if ( movingOperation == ResizingRight ) { + movingGVItem->setEndTime( dt.addSecs( duration ) ); + } + movingStart = e->pos(); + } + + static int moves = 0; + if ( (currentLink || currentItem) && (moves < 3) ) { + ++moves; + } else { + moves = 0; + currentLink = 0; + currentItem = 0; + } + if (autoScrollEnabled) + mousePos = e->pos()- QPoint(contentsX(),contentsY()); // make mousePos relative 0 + if (fromItem) { + //qDebug("mousemove: linking %s: %d,%d ",fromItem->listViewText().latin1(), e->pos().x(), e->pos().y()); + linkLine->setPoints(linkLine->startPoint().x(), linkLine->startPoint().y(), e->pos().x(), e->pos().y()); + canvas()->update(); + } + // no action implemented +} +void KDGanttCanvasView::viewportPaintEvent ( QPaintEvent * pe ) +{ + QCanvasView::viewportPaintEvent ( pe ); +} +void KDGanttCanvasView::set_Mouse_Tracking(bool on) +{ + viewport()->setMouseTracking(on); +} +int KDGanttCanvasView::getType(QCanvasItem* it) +{ + switch (it->rtti()) { + case QCanvasItem::Rtti_Line: return ((KDCanvasLine*)it)->myParentType; + case QCanvasItem::Rtti_Ellipse: return ((KDCanvasEllipse *)it)->myParentType; + case QCanvasItem::Rtti_Text: return ((KDCanvasText *)it)->myParentType; + case QCanvasItem::Rtti_Polygon: return ((KDCanvasPolygon *)it)->myParentType; + case QCanvasItem::Rtti_Rectangle: + case KDIntervalColorRectangle::RTTI: + return ((KDCanvasRectangle *)it)->myParentType; + } + return -1; +} +KDGanttViewItem* KDGanttCanvasView::getItem(QCanvasItem* it) +{ + switch (it->rtti()) { + case QCanvasItem::Rtti_Line: return (KDGanttViewItem*) ((KDCanvasLine*)it)->myParentItem; + case QCanvasItem::Rtti_Ellipse: return (KDGanttViewItem*) ((KDCanvasEllipse *)it)->myParentItem; + case QCanvasItem::Rtti_Text: return (KDGanttViewItem*) ((KDCanvasText *)it)->myParentItem; + case QCanvasItem::Rtti_Polygon: return (KDGanttViewItem*) ((KDCanvasPolygon *)it)->myParentItem; + case QCanvasItem::Rtti_Rectangle: return (KDGanttViewItem*) ((KDCanvasRectangle *)it)->myParentItem; + + } + return 0; +} +KDGanttViewTaskLink* KDGanttCanvasView::getLink(QCanvasItem* it) +{ + switch (it->rtti()) { + case QCanvasItem::Rtti_Line: return (KDGanttViewTaskLink*) ((KDCanvasLine*)it)->myParentItem; + case QCanvasItem::Rtti_Ellipse: return (KDGanttViewTaskLink*) ((KDCanvasEllipse *)it)->myParentItem; + case QCanvasItem::Rtti_Text: return (KDGanttViewTaskLink*) ((KDCanvasText *)it)->myParentItem; + case QCanvasItem::Rtti_Polygon: return (KDGanttViewTaskLink*) ((KDCanvasPolygon *)it)->myParentItem; + } + return 0; +} + +void KDGanttCanvasView::slotScrollTimer() { + int mx = mousePos.x(); + int my = mousePos.y(); + int dx = 0; + int dy = 0; + if (mx < 0) + dx = -5; + else if (mx > visibleWidth()) + dx = 5; + if (my < 0) + dy = -5; + else if (my > visibleHeight()) + dy = QMIN(5, verticalScrollBar()->maxValue()-verticalScrollBar()->value()); + + if (dx != 0 || dy != 0) + scrollBy(dx, dy); +} + +int KDGanttCanvasView::getItemArea(KDGanttViewItem *item, int x) { + // area can be: no area = 0, Start = 1, Finish = 2 + // TODO: middle (move, dnd), front, back (resize) + KDTimeTableWidget *tt = dynamic_cast<KDTimeTableWidget *>(canvas()); + if (!tt) { + qWarning("Cannot cast canvas to KDTimeTableWidget"); + return 0; + } + int area = 0; + int start = tt->getCoordX(item->startTime()); + int end = start; + if (item->type() == KDGanttViewItem::Event) { + x > start ? area = 2 : area = 1; + } else { + end = tt->getCoordX(item->endTime()); + if ((end - start)/2 > (x - start)) + area = 1; + else + area = 2; + } + return area; +} + +int KDGanttCanvasView::getLinkType(int from, int to) { + // from, to should be Start = 1 or Finish = 2 + if ((from == 1) && (to == 1)) { + return KDGanttViewTaskLink::StartStart; + } + if ((from == 1) && (to == 2)) { + return KDGanttViewTaskLink::StartFinish; + } + if ((from == 2) && (to == 1)) { + return KDGanttViewTaskLink::FinishStart; + } + if ((from == 2) && (to == 2)) { + return KDGanttViewTaskLink::FinishFinish; + } + return KDGanttViewTaskLink::None; +} + +/*! + Represents the background color for a given interval of time (across all tasks). + \sa KDGanttView::addIntervalBackgroundColor + \param view parent view + */ +KDIntervalColorRectangle::KDIntervalColorRectangle( KDGanttView* view ) + : KDCanvasRectangle( view->timeTableWidget(), 0, Type_is_KDGanttGridItem ), + mStart(), mEnd() +{ + setZ( -19 ); +} + +/*! + \param start start datetime of the time interval + \param end end datetime of the time interval + */ +void KDIntervalColorRectangle::setDateTimes( const QDateTime& start, + const QDateTime& end ) +{ + mStart = start; + mEnd = end; + if ( mEnd < mStart ) + qSwap( mStart, mEnd ); +} + +/*! + Sets the background color + \param color the background color +*/ +void KDIntervalColorRectangle::setColor( const QColor& color ) +{ + mColor = color; +} + +/*! + \internal +*/ +void KDIntervalColorRectangle::layout( KDTimeHeaderWidget* timeHeader, int height ) +{ + int left = timeHeader->getCoordX(mStart); + int right = timeHeader->getCoordX(mEnd); + if ( right == left ) + ++right; + setPen( QPen::NoPen ); + setBrush( QBrush(mColor, SolidPattern) ); + setSize( right - left, height ); + move( left, 0 ); + show(); +} + +/*! + \internal +*/ +KDIntervalColorRectangle::HitTest KDIntervalColorRectangle::hitTest( KDTimeHeaderWidget* timeHeader, const QPoint& pos ) const +{ + const int left = timeHeader->getCoordX(mStart); + const int right = timeHeader->getCoordX(mEnd); + const int width = right - left + 1; + const int x = pos.x(); + if ( x < left + width / 10 ) + return Start; + if ( x > right - width / 10 ) + return End; + return Middle; +} |