00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <libkcal/calendar.h>
00027 #include <libkcal/calendarresources.h>
00028
00029 #include <qlayout.h>
00030
00031 #include <kdgantt/KDGanttViewTaskItem.h>
00032 #include <kdgantt/KDGanttViewSubwidgets.h>
00033
00034 #include "koeventpopupmenu.h"
00035 #include "koglobals.h"
00036 #include "koprefs.h"
00037 #include "timelineitem.h"
00038
00039 #include "kotimelineview.h"
00040
00041 using namespace KOrg;
00042 using namespace KCal;
00043
00044 KOTimelineView::KOTimelineView(Calendar *calendar, QWidget *parent,
00045 const char *name)
00046 : KOEventView(calendar, parent, name),
00047 mEventPopup( 0 )
00048 {
00049 QVBoxLayout* vbox = new QVBoxLayout(this);
00050 mGantt = new KDGanttView(this);
00051 mGantt->setCalendarMode( true );
00052 mGantt->setShowLegendButton( false );
00053 mGantt->setFixedHorizon( true );
00054 mGantt->removeColumn( 0 );
00055 mGantt->addColumn( i18n("Calendar") );
00056 mGantt->setHeaderVisible( true );
00057 if ( KGlobal::locale()->use12Clock() )
00058 mGantt->setHourFormat( KDGanttView::Hour_12 );
00059 else
00060 mGantt->setHourFormat( KDGanttView::Hour_24_FourDigit );
00061
00062
00063 vbox->addWidget( mGantt );
00064
00065 connect( mGantt, SIGNAL(gvCurrentChanged(KDGanttViewItem*)),
00066 SLOT(itemSelected(KDGanttViewItem*)) );
00067 connect( mGantt, SIGNAL(itemDoubleClicked(KDGanttViewItem*)),
00068 SLOT(itemDoubleClicked(KDGanttViewItem*)) );
00069 connect( mGantt, SIGNAL(itemRightClicked(KDGanttViewItem*)),
00070 SLOT(itemRightClicked(KDGanttViewItem*)) );
00071 connect( mGantt, SIGNAL(gvItemMoved(KDGanttViewItem*)),
00072 SLOT(itemMoved(KDGanttViewItem*)) );
00073 connect( mGantt, SIGNAL(rescaling(KDGanttView::Scale)),
00074 SLOT(overscale(KDGanttView::Scale)) );
00075 connect( mGantt, SIGNAL( dateTimeDoubleClicked( const QDateTime& ) ),
00076 SLOT( newEventWithHint( const QDateTime& ) ) );
00077 }
00078
00079 KOTimelineView::~KOTimelineView()
00080 {
00081 delete mEventPopup;
00082 }
00083
00084
00085 KCal::ListBase<KCal::Incidence> KOTimelineView::selectedIncidences()
00086 {
00087 return KCal::ListBase<KCal::Incidence>();
00088 }
00089
00090
00091 KCal::DateList KOTimelineView::selectedIncidenceDates()
00092 {
00093 return KCal::DateList();
00094 }
00095
00096
00097 int KOTimelineView::currentDateCount()
00098 {
00099 return 0;
00100 }
00101
00102
00103 void KOTimelineView::showDates(const QDate& start, const QDate& end)
00104 {
00105 mStartDate = start;
00106 mEndDate = end;
00107 mHintDate = QDateTime();
00108 mGantt->setHorizonStart( QDateTime(start) );
00109 mGantt->setHorizonEnd( QDateTime(end.addDays(1)) );
00110 mGantt->setMinorScaleCount( 1 );
00111 mGantt->setScale( KDGanttView::Hour );
00112 mGantt->setMinimumScale( KDGanttView::Hour );
00113 mGantt->setMaximumScale( KDGanttView::Hour );
00114 mGantt->zoomToFit();
00115
00116 mGantt->setUpdateEnabled( false );
00117 mGantt->clear();
00118
00119
00120 TimelineItem *item = 0;
00121 CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
00122 if ( !calres ) {
00123 item = new TimelineItem( i18n("Calendar"), calendar(), mGantt );
00124 mCalendarItemMap[0][QString()] = item;
00125 } else {
00126 CalendarResourceManager *manager = calres->resourceManager();
00127 for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) {
00128 QColor resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
00129 if ( (*it)->canHaveSubresources() ) {
00130 QStringList subResources = (*it)->subresources();
00131 for ( QStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) {
00132 QString type = (*it)->subresourceType( *subit );
00133 if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") )
00134 continue;
00135 item = new TimelineItem( (*it)->labelForSubresource( *subit ), calendar(), mGantt );
00136 resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
00137 QColor subrescol = *KOPrefs::instance()->resourceColor( *subit );
00138 if ( subrescol.isValid() )
00139 resourceColor = subrescol;
00140 if ( resourceColor.isValid() )
00141 item->setColors( resourceColor, resourceColor, resourceColor );
00142 mCalendarItemMap[*it][*subit] = item;
00143 }
00144 } else {
00145 item = new TimelineItem( (*it)->resourceName(), calendar(), mGantt );
00146 if ( resourceColor.isValid() )
00147 item->setColors( resourceColor, resourceColor, resourceColor );
00148 mCalendarItemMap[*it][QString()] = item;
00149 }
00150 }
00151 }
00152
00153
00154 Event::List events;
00155 for ( QDate day = start; day <= end; day = day.addDays( 1 ) ) {
00156 events = calendar()->events( day, EventSortStartDate, SortDirectionAscending );
00157 for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) {
00158 insertIncidence( *it, day );
00159 }
00160 }
00161
00162 mGantt->setUpdateEnabled( true );
00163 }
00164
00165
00166 void KOTimelineView::showIncidences(const KCal::ListBase<KCal::Incidence>&, const QDate &)
00167 {
00168 }
00169
00170
00171 void KOTimelineView::updateView()
00172 {
00173 if ( mStartDate.isValid() && mEndDate.isValid() )
00174 showDates( mStartDate, mEndDate );
00175 }
00176
00177
00178 void KOTimelineView::changeIncidenceDisplay(KCal::Incidence* incidence, int mode)
00179 {
00180 kdDebug() << k_funcinfo << incidence << " " << mode << endl;
00181 switch ( mode ) {
00182 case KOGlobals::INCIDENCEADDED:
00183 insertIncidence( incidence );
00184 break;
00185 case KOGlobals::INCIDENCEEDITED:
00186 removeIncidence( incidence );
00187 insertIncidence( incidence );
00188 break;
00189 case KOGlobals::INCIDENCEDELETED:
00190 removeIncidence( incidence );
00191 break;
00192 default:
00193 updateView();
00194 }
00195 }
00196
00197 void KOTimelineView::itemSelected( KDGanttViewItem *item )
00198 {
00199 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
00200 if ( tlitem )
00201 emit incidenceSelected( tlitem->incidence(), tlitem->originalStart().date() );
00202 }
00203
00204 void KOTimelineView::itemDoubleClicked( KDGanttViewItem *item )
00205 {
00206 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
00207 if ( tlitem ) {
00208 emit editIncidenceSignal( tlitem->incidence(), QDate() );
00209 }
00210 }
00211
00212 void KOTimelineView::itemRightClicked( KDGanttViewItem *item )
00213 {
00214 mHintDate = mGantt->getDateTimeForCoordX( QCursor::pos().x(), true );
00215 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
00216 if ( !tlitem ) {
00217 showNewEventPopup();
00218 return;
00219 }
00220 if ( !mEventPopup )
00221 mEventPopup = eventPopup();
00222 mEventPopup->showIncidencePopup( calendar(), tlitem->incidence(), QDate() );
00223 }
00224
00225 bool KOTimelineView::eventDurationHint(QDateTime & startDt, QDateTime & endDt, bool & allDay)
00226 {
00227 startDt = mHintDate;
00228 endDt = mHintDate.addSecs( 2 * 60 * 60 );
00229 allDay = false;
00230 return mHintDate.isValid();
00231 }
00232
00233
00234 void KOTimelineView::newEventWithHint( const QDateTime& dt )
00235 {
00236 mHintDate = dt;
00237 emit newEventSignal( 0, QString(), dt );
00238 }
00239
00240 TimelineItem * KOTimelineView::calendarItemForIncidence(KCal::Incidence * incidence)
00241 {
00242 CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
00243 TimelineItem *item = 0;
00244 if ( !calres ) {
00245 item = mCalendarItemMap[0][QString()];
00246 } else {
00247 ResourceCalendar *res = calres->resource( incidence );
00248 if ( !res )
00249 return 0;
00250 if ( res->canHaveSubresources() ) {
00251 QString subRes = res->subresourceIdentifier( incidence );
00252 item = mCalendarItemMap[res][subRes];
00253 } else {
00254 item = mCalendarItemMap[res][QString()];
00255 }
00256 }
00257 return item;
00258 }
00259
00260 void KOTimelineView::insertIncidence(KCal::Incidence * incidence, const QDate &day )
00261 {
00262 TimelineItem *item = calendarItemForIncidence( incidence );
00263 if ( !item ) {
00264 kdWarning() << k_funcinfo << "Help! Something is really wrong here!" << endl;
00265 return;
00266 }
00267
00268 if ( incidence->doesRecur() ) {
00269 QValueList<QDateTime> l = incidence->startDateTimesForDate( day );
00270 if ( l.isEmpty() ) {
00271
00272 item->insertIncidence( incidence, QDateTime( day, incidence->dtStart().time() ),
00273 QDateTime( day, incidence->dtEnd().time() ) );
00274 } else {
00275 for ( QValueList<QDateTime>::ConstIterator it = l.constBegin();
00276 it != l.constEnd(); ++it ) {
00277 item->insertIncidence( incidence, *it, incidence->endDateForStart( *it ) );
00278 }
00279 }
00280 } else {
00281 if ( incidence->dtStart().date() == day || incidence->dtStart().date() < mStartDate )
00282 item->insertIncidence( incidence );
00283 }
00284 }
00285
00286 void KOTimelineView::insertIncidence(KCal::Incidence * incidence)
00287 {
00288 KCal::Event *event = dynamic_cast<KCal::Event*>( incidence );
00289 if ( !event )
00290 return;
00291 if ( incidence->doesRecur() )
00292 insertIncidence( incidence, QDate() );
00293 for ( QDate day = mStartDate; day <= mEndDate; day = day.addDays( 1 ) ) {
00294 Event::List events = calendar()->events( day, EventSortStartDate, SortDirectionAscending );
00295 for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) {
00296 if ( events.contains( event ) )
00297 insertIncidence( *it, day );
00298 }
00299 }
00300 }
00301
00302 void KOTimelineView::removeIncidence(KCal::Incidence * incidence)
00303 {
00304 TimelineItem *item = calendarItemForIncidence( incidence );
00305 if ( item ) {
00306 item->removeIncidence( incidence );
00307 } else {
00308
00309 typedef QMap<QString, KOrg::TimelineItem*> M2_t;
00310 typedef QMap<KCal::ResourceCalendar*, M2_t> M1_t;
00311 for ( M1_t::ConstIterator it1 = mCalendarItemMap.constBegin(); it1 != mCalendarItemMap.constEnd(); ++it1 ) {
00312 for ( M2_t::ConstIterator it2 = it1.data().constBegin(); it2 != it1.data().constEnd(); ++it2 ) {
00313 if ( it2.data() ) {
00314 it2.data()->removeIncidence( incidence );
00315 }
00316 }
00317 }
00318 }
00319 }
00320
00321 void KOTimelineView::itemMoved(KDGanttViewItem * item)
00322 {
00323 TimelineSubItem *tlit = dynamic_cast<TimelineSubItem*>( item );
00324 if ( !tlit )
00325 return;
00326 Incidence *i = tlit->incidence();
00327 mChanger->beginChange( i, 0, QString() );
00328 QDateTime newStart = tlit->startTime();
00329 if ( i->doesFloat() )
00330 newStart = QDateTime( newStart.date() );
00331 int delta = tlit->originalStart().secsTo( newStart );
00332 i->setDtStart( i->dtStart().addSecs( delta ) );
00333 int duration = tlit->startTime().secsTo( tlit->endTime() );
00334 int allDayOffset = 0;
00335 if ( i->doesFloat() ) {
00336 duration /= (60*60*24);
00337 duration *= (60*60*24);
00338 allDayOffset = (60*60*24);
00339 duration -= allDayOffset;
00340 if ( duration < 0 ) duration = 0;
00341 }
00342 i->setDuration( duration );
00343 TimelineItem *parent = static_cast<TimelineItem*>( tlit->parent() );
00344 parent->moveItems( i, tlit->originalStart().secsTo( newStart ), duration + allDayOffset );
00345 mChanger->endChange( i, 0, QString() );
00346 }
00347
00348 void KOTimelineView::overscale(KDGanttView::Scale scale)
00349 {
00350 Q_UNUSED( scale );
00351 mGantt->setZoomFactor( 1, false );
00352 mGantt->setScale( KDGanttView::Hour );
00353 mGantt->setMinorScaleCount( 12 );
00354 }
00355
00356 #include "kotimelineview.moc"