summaryrefslogtreecommitdiffstats
path: root/korganizer/kotimelineview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'korganizer/kotimelineview.cpp')
-rw-r--r--korganizer/kotimelineview.cpp355
1 files changed, 355 insertions, 0 deletions
diff --git a/korganizer/kotimelineview.cpp b/korganizer/kotimelineview.cpp
new file mode 100644
index 000000000..24f981a53
--- /dev/null
+++ b/korganizer/kotimelineview.cpp
@@ -0,0 +1,355 @@
+/*
+ This file is part of KOrganizer.
+
+ Copyright (c) 2007 Till Adam <adam@kde.org>
+
+ 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 <libkcal/calendar.h>
+#include <libkcal/calendarresources.h>
+
+#include <qlayout.h>
+
+#include <kdgantt/KDGanttViewTaskItem.h>
+#include <kdgantt/KDGanttViewSubwidgets.h>
+
+#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, QWidget *parent,
+ const char *name)
+ : KOEventView(calendar, parent, name),
+ mEventPopup( 0 )
+{
+ QVBoxLayout* vbox = new QVBoxLayout(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, SIGNAL(gvCurrentChanged(KDGanttViewItem*)),
+ SLOT(itemSelected(KDGanttViewItem*)) );
+ connect( mGantt, SIGNAL(itemDoubleClicked(KDGanttViewItem*)),
+ SLOT(itemDoubleClicked(KDGanttViewItem*)) );
+ connect( mGantt, SIGNAL(itemRightClicked(KDGanttViewItem*)),
+ SLOT(itemRightClicked(KDGanttViewItem*)) );
+ connect( mGantt, SIGNAL(gvItemMoved(KDGanttViewItem*)),
+ SLOT(itemMoved(KDGanttViewItem*)) );
+ connect( mGantt, SIGNAL(rescaling(KDGanttView::Scale)),
+ SLOT(overscale(KDGanttView::Scale)) );
+ connect( mGantt, SIGNAL( dateTimeDoubleClicked( const QDateTime& ) ),
+ SLOT( newEventWithHint( const QDateTime& ) ) );
+}
+
+KOTimelineView::~KOTimelineView()
+{
+ delete mEventPopup;
+}
+
+/*virtual*/
+KCal::ListBase<KCal::Incidence> KOTimelineView::selectedIncidences()
+{
+ return KCal::ListBase<KCal::Incidence>();
+}
+
+/*virtual*/
+KCal::DateList KOTimelineView::selectedDates()
+{
+ return KCal::DateList();
+}
+
+/*virtual*/
+int KOTimelineView::currentDateCount()
+{
+ return 0;
+}
+
+/*virtual*/
+void KOTimelineView::showDates(const QDate& start, const QDate& end)
+{
+ mStartDate = start;
+ mEndDate = end;
+ mHintDate = QDateTime();
+ mGantt->setHorizonStart( QDateTime(start) );
+ mGantt->setHorizonEnd( QDateTime(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<CalendarResources*>( calendar() );
+ if ( !calres ) {
+ item = new TimelineItem( i18n("Calendar"), mGantt );
+ mCalendarItemMap[0][QString()] = item;
+ } else {
+ CalendarResourceManager *manager = calres->resourceManager();
+ for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) {
+ QColor resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
+ if ( (*it)->canHaveSubresources() ) {
+ QStringList subResources = (*it)->subresources();
+ for ( QStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) {
+ QString type = (*it)->subresourceType( *subit );
+ if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") )
+ continue;
+ item = new TimelineItem( (*it)->labelForSubresource( *subit ), mGantt );
+ resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
+ QColor 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(), mGantt );
+ if ( resourceColor.isValid() )
+ item->setColors( resourceColor, resourceColor, resourceColor );
+ mCalendarItemMap[*it][QString()] = item;
+ }
+ }
+ }
+
+ // add incidences
+ Event::List events;
+ for ( QDate 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<KCal::Incidence>&)
+{
+}
+
+/*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<TimelineSubItem*>( item );
+ if ( tlitem )
+ emit incidenceSelected( tlitem->incidence() );
+}
+
+void KOTimelineView::itemDoubleClicked( KDGanttViewItem *item )
+{
+ TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
+ if ( tlitem )
+ emit editIncidenceSignal( tlitem->incidence() );
+}
+
+void KOTimelineView::itemRightClicked( KDGanttViewItem *item )
+{
+ mHintDate = mGantt->getDateTimeForCoordX( QCursor::pos().x(), true );
+ TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
+ if ( !tlitem ) {
+ showNewEventPopup();
+ return;
+ }
+ if ( !mEventPopup )
+ mEventPopup = eventPopup();
+ mEventPopup->showIncidencePopup( tlitem->incidence(), QDate() );
+}
+
+bool KOTimelineView::eventDurationHint(QDateTime & startDt, QDateTime & endDt, bool & allDay)
+{
+ startDt = mHintDate;
+ endDt = mHintDate.addSecs( 2 * 60 * 60 );
+ allDay = false;
+ return mHintDate.isValid();
+}
+
+//slot
+void KOTimelineView::newEventWithHint( const QDateTime& dt )
+{
+ mHintDate = dt;
+ emit newEventSignal( dt );
+}
+
+TimelineItem * KOTimelineView::calendarItemForIncidence(KCal::Incidence * incidence)
+{
+ CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
+ TimelineItem *item = 0;
+ if ( !calres ) {
+ item = mCalendarItemMap[0][QString()];
+ } else {
+ ResourceCalendar *res = calres->resource( incidence );
+ if ( !res )
+ return 0;
+ if ( res->canHaveSubresources() ) {
+ QString subRes = res->subresourceIdentifier( incidence );
+ item = mCalendarItemMap[res][subRes];
+ } else {
+ item = mCalendarItemMap[res][QString()];
+ }
+ }
+ return item;
+}
+
+void KOTimelineView::insertIncidence(KCal::Incidence * incidence, const QDate &day )
+{
+ TimelineItem *item = calendarItemForIncidence( incidence );
+ if ( !item ) {
+ kdWarning() << k_funcinfo << "Help! Something is really wrong here!" << endl;
+ return;
+ }
+
+ if ( incidence->doesRecur() ) {
+ QValueList<QDateTime> l = incidence->startDateTimesForDate( day );
+ if ( l.isEmpty() ) {
+ // strange, but seems to happen for some recurring events...
+ item->insertIncidence( incidence, QDateTime( day, incidence->dtStart().time() ),
+ QDateTime( day, incidence->dtEnd().time() ) );
+ } else {
+ for ( QValueList<QDateTime>::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<KCal::Event*>( incidence );
+ if ( !event )
+ return;
+ if ( incidence->doesRecur() )
+ insertIncidence( incidence, QDate() );
+ for ( QDate 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 QMap<QString, KOrg::TimelineItem*> M2_t;
+ typedef QMap<KCal::ResourceCalendar*, M2_t> 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<TimelineSubItem*>( item );
+ if ( !tlit )
+ return;
+ Incidence *i = tlit->incidence();
+ mChanger->beginChange( i );
+ QDateTime newStart = tlit->startTime();
+ if ( i->doesFloat() )
+ newStart = QDateTime( 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<TimelineItem*>( tlit->parent() );
+ parent->moveItems( i, tlit->originalStart().secsTo( newStart ), duration + allDayOffset );
+ mChanger->endChange( i );
+}
+
+void KOTimelineView::overscale(KDGanttView::Scale scale)
+{
+ Q_UNUSED( scale );
+ mGantt->setZoomFactor( 1, false );
+ mGantt->setScale( KDGanttView::Hour );
+ mGantt->setMinorScaleCount( 12 );
+}
+
+#include "kotimelineview.moc"