/* This file is part of KOrganizer. Copyright (c) 2007 Till Adam This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 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 #include #include #include #include #include "koeventpopupmenu.h" #include "koglobals.h" #include "koprefs.h" #include "timelineitem.h" #include "kotimelineview.h" using namespace KOrg; using namespace KCal; KOTimelineView::KOTimelineView(Calendar *calendar, TQWidget *parent, const char *name) : KOEventView(calendar, parent, name), mEventPopup( 0 ) { TQVBoxLayout* vbox = new TQVBoxLayout(this); mGantt = new KDGanttView(this); mGantt->setCalendarMode( true ); mGantt->setShowLegendButton( false ); mGantt->setFixedHorizon( true ); mGantt->removeColumn( 0 ); mGantt->addColumn( i18n("Calendar") ); mGantt->setHeaderVisible( true ); if ( KGlobal::locale()->use12Clock() ) mGantt->setHourFormat( KDGanttView::Hour_12 ); else mGantt->setHourFormat( KDGanttView::Hour_24_FourDigit ); vbox->addWidget( mGantt ); connect( mGantt, TQT_SIGNAL(gvCurrentChanged(KDGanttViewItem*)), TQT_SLOT(itemSelected(KDGanttViewItem*)) ); connect( mGantt, TQT_SIGNAL(itemDoubleClicked(KDGanttViewItem*)), TQT_SLOT(itemDoubleClicked(KDGanttViewItem*)) ); connect( mGantt, TQT_SIGNAL(itemRightClicked(KDGanttViewItem*)), TQT_SLOT(itemRightClicked(KDGanttViewItem*)) ); connect( mGantt, TQT_SIGNAL(gvItemMoved(KDGanttViewItem*)), TQT_SLOT(itemMoved(KDGanttViewItem*)) ); connect( mGantt, TQT_SIGNAL(rescaling(KDGanttView::Scale)), TQT_SLOT(overscale(KDGanttView::Scale)) ); connect( mGantt, TQT_SIGNAL( dateTimeDoubleClicked( const TQDateTime& ) ), TQT_SLOT( newEventWithHint( const TQDateTime& ) ) ); } KOTimelineView::~KOTimelineView() { delete mEventPopup; } /*virtual*/ KCal::ListBase KOTimelineView::selectedIncidences() { return KCal::ListBase(); } /*virtual*/ KCal::DateList KOTimelineView::selectedIncidenceDates() { return KCal::DateList(); } /*virtual*/ int KOTimelineView::currentDateCount() { return 0; } /*virtual*/ void KOTimelineView::showDates(const TQDate& start, const TQDate& end) { mStartDate = start; mEndDate = end; mHintDate = TQDateTime(); mGantt->setHorizonStart( TQDateTime(start) ); mGantt->setHorizonEnd( TQDateTime(end.addDays(1)) ); mGantt->setMinorScaleCount( 1 ); mGantt->setScale( KDGanttView::Hour ); mGantt->setMinimumScale( KDGanttView::Hour ); mGantt->setMaximumScale( KDGanttView::Hour ); mGantt->zoomToFit(); mGantt->setUpdateEnabled( false ); mGantt->clear(); // item for every calendar TimelineItem *item = 0; CalendarResources *calres = dynamic_cast( calendar() ); if ( !calres ) { item = new TimelineItem( i18n("Calendar"), calendar(), mGantt ); mCalendarItemMap[0][TQString()] = item; } else { CalendarResourceManager *manager = calres->resourceManager(); for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) { TQColor resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() ); if ( (*it)->canHaveSubresources() ) { TQStringList subResources = (*it)->subresources(); for ( TQStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) { TQString type = (*it)->subresourceType( *subit ); if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") ) continue; item = new TimelineItem( (*it)->labelForSubresource( *subit ), calendar(), mGantt ); resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() ); TQColor subrescol = *KOPrefs::instance()->resourceColor( *subit ); if ( subrescol.isValid() ) resourceColor = subrescol; if ( resourceColor.isValid() ) item->setColors( resourceColor, resourceColor, resourceColor ); mCalendarItemMap[*it][*subit] = item; } } else { item = new TimelineItem( (*it)->resourceName(), calendar(), mGantt ); if ( resourceColor.isValid() ) item->setColors( resourceColor, resourceColor, resourceColor ); mCalendarItemMap[*it][TQString()] = item; } } } // add incidences Event::List events; for ( TQDate day = start; day <= end; day = day.addDays( 1 ) ) { events = calendar()->events( day, EventSortStartDate, SortDirectionAscending ); for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) { insertIncidence( *it, day ); } } mGantt->setUpdateEnabled( true ); } /*virtual*/ void KOTimelineView::showIncidences(const KCal::ListBase&, const TQDate &) { } /*virtual*/ void KOTimelineView::updateView() { if ( mStartDate.isValid() && mEndDate.isValid() ) showDates( mStartDate, mEndDate ); } /*virtual*/ void KOTimelineView::changeIncidenceDisplay(KCal::Incidence* incidence, int mode) { kdDebug() << k_funcinfo << incidence << " " << mode << endl; switch ( mode ) { case KOGlobals::INCIDENCEADDED: insertIncidence( incidence ); break; case KOGlobals::INCIDENCEEDITED: removeIncidence( incidence ); insertIncidence( incidence ); break; case KOGlobals::INCIDENCEDELETED: removeIncidence( incidence ); break; default: updateView(); } } void KOTimelineView::itemSelected( KDGanttViewItem *item ) { TimelineSubItem *tlitem = dynamic_cast( item ); if ( tlitem ) emit incidenceSelected( tlitem->incidence(), tlitem->originalStart().date() ); } void KOTimelineView::itemDoubleClicked( KDGanttViewItem *item ) { TimelineSubItem *tlitem = dynamic_cast( item ); if ( tlitem ) { emit editIncidenceSignal( tlitem->incidence(), TQDate() ); } } void KOTimelineView::itemRightClicked( KDGanttViewItem *item ) { mHintDate = mGantt->getDateTimeForCoordX( TQCursor::pos().x(), true ); TimelineSubItem *tlitem = dynamic_cast( item ); if ( !tlitem ) { showNewEventPopup(); return; } if ( !mEventPopup ) mEventPopup = eventPopup(); mEventPopup->showIncidencePopup( calendar(), tlitem->incidence(), TQDate() ); } bool KOTimelineView::eventDurationHint(TQDateTime & startDt, TQDateTime & endDt, bool & allDay) { startDt = mHintDate; endDt = mHintDate.addSecs( 2 * 60 * 60 ); allDay = false; return mHintDate.isValid(); } //slot void KOTimelineView::newEventWithHint( const TQDateTime& dt ) { mHintDate = dt; emit newEventSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, dt ); } TimelineItem * KOTimelineView::calendarItemForIncidence(KCal::Incidence * incidence) { CalendarResources *calres = dynamic_cast( calendar() ); TimelineItem *item = 0; if ( !calres ) { item = mCalendarItemMap[0][TQString()]; } else { ResourceCalendar *res = calres->resource( incidence ); if ( !res ) return 0; if ( res->canHaveSubresources() ) { TQString subRes = res->subresourceIdentifier( incidence ); item = mCalendarItemMap[res][subRes]; } else { item = mCalendarItemMap[res][TQString()]; } } return item; } void KOTimelineView::insertIncidence(KCal::Incidence * incidence, const TQDate &day ) { TimelineItem *item = calendarItemForIncidence( incidence ); if ( !item ) { kdWarning() << k_funcinfo << "Help! Something is really wrong here!" << endl; return; } if ( incidence->doesRecur() ) { TQValueList l = incidence->startDateTimesForDate( day ); if ( l.isEmpty() ) { // strange, but seems to happen for some recurring events... item->insertIncidence( incidence, TQDateTime( day, incidence->dtStart().time() ), TQDateTime( day, incidence->dtEnd().time() ) ); } else { for ( TQValueList::ConstIterator it = l.constBegin(); it != l.constEnd(); ++it ) { item->insertIncidence( incidence, *it, incidence->endDateForStart( *it ) ); } } } else { if ( incidence->dtStart().date() == day || incidence->dtStart().date() < mStartDate ) item->insertIncidence( incidence ); } } void KOTimelineView::insertIncidence(KCal::Incidence * incidence) { KCal::Event *event = dynamic_cast( incidence ); if ( !event ) return; if ( incidence->doesRecur() ) insertIncidence( incidence, TQDate() ); for ( TQDate day = mStartDate; day <= mEndDate; day = day.addDays( 1 ) ) { Event::List events = calendar()->events( day, EventSortStartDate, SortDirectionAscending ); for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) { if ( events.contains( event ) ) insertIncidence( *it, day ); } } } void KOTimelineView::removeIncidence(KCal::Incidence * incidence) { TimelineItem *item = calendarItemForIncidence( incidence ); if ( item ) { item->removeIncidence( incidence ); } else { // try harder, the incidence might already be removed from the resource typedef TQMap M2_t; typedef TQMap M1_t; for ( M1_t::ConstIterator it1 = mCalendarItemMap.constBegin(); it1 != mCalendarItemMap.constEnd(); ++it1 ) { for ( M2_t::ConstIterator it2 = it1.data().constBegin(); it2 != it1.data().constEnd(); ++it2 ) { if ( it2.data() ) { it2.data()->removeIncidence( incidence ); } } } } } void KOTimelineView::itemMoved(KDGanttViewItem * item) { TimelineSubItem *tlit = dynamic_cast( item ); if ( !tlit ) return; Incidence *i = tlit->incidence(); mChanger->beginChange( i, 0, TQString() ); TQDateTime newStart = tlit->startTime(); if ( i->doesFloat() ) newStart = TQDateTime( newStart.date() ); int delta = tlit->originalStart().secsTo( newStart ); i->setDtStart( i->dtStart().addSecs( delta ) ); int duration = tlit->startTime().secsTo( tlit->endTime() ); int allDayOffset = 0; if ( i->doesFloat() ) { duration /= (60*60*24); duration *= (60*60*24); allDayOffset = (60*60*24); duration -= allDayOffset; if ( duration < 0 ) duration = 0; } i->setDuration( duration ); TimelineItem *parent = static_cast( tlit->parent() ); parent->moveItems( i, tlit->originalStart().secsTo( newStart ), duration + allDayOffset ); mChanger->endChange( i, 0, TQString() ); } void KOTimelineView::overscale(KDGanttView::Scale scale) { Q_UNUSED( scale ); mGantt->setZoomFactor( 1, false ); mGantt->setScale( KDGanttView::Hour ); mGantt->setMinorScaleCount( 12 ); } #include "kotimelineview.moc"