korganizer

kotimelineview.cpp
1/*
2 This file is part of KOrganizer.
3
4 Copyright (c) 2007 Till Adam <adam@kde.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 As a special exception, permission is given to link this program
21 with any edition of TQt, and distribute the resulting executable,
22 without including the source code for TQt in the source distribution.
23*/
24
25
26#include <libkcal/calendar.h>
28
29#include <tqlayout.h>
30
31#include <kdgantt/KDGanttViewTaskItem.h>
32#include <kdgantt/KDGanttViewSubwidgets.h>
33
34#include "koeventpopupmenu.h"
35#include "koglobals.h"
36#include "koprefs.h"
37#include "timelineitem.h"
38
39#include "kotimelineview.h"
40
41using namespace KOrg;
42using namespace KCal;
43
44KOTimelineView::KOTimelineView(Calendar *calendar, TQWidget *parent,
45 const char *name)
46 : KOEventView(calendar, parent, name),
47 mEventPopup( 0 )
48{
49 TQVBoxLayout* vbox = new TQVBoxLayout(this);
50 mGantt = new KDGanttView(this);
51 mGantt->setCalendarMode( true );
52 mGantt->setShowLegendButton( false );
53 mGantt->setFixedHorizon( true );
54 mGantt->removeColumn( 0 );
55 mGantt->addColumn( i18n("Calendar") );
56 mGantt->setHeaderVisible( true );
57 if ( TDEGlobal::locale()->use12Clock() )
58 mGantt->setHourFormat( KDGanttView::Hour_12 );
59 else
60 mGantt->setHourFormat( KDGanttView::Hour_24_FourDigit );
61
62
63 vbox->addWidget( mGantt );
64
65 connect( mGantt, TQ_SIGNAL(gvCurrentChanged(KDGanttViewItem*)),
66 TQ_SLOT(itemSelected(KDGanttViewItem*)) );
67 connect( mGantt, TQ_SIGNAL(itemDoubleClicked(KDGanttViewItem*)),
68 TQ_SLOT(itemDoubleClicked(KDGanttViewItem*)) );
69 connect( mGantt, TQ_SIGNAL(itemRightClicked(KDGanttViewItem*)),
70 TQ_SLOT(itemRightClicked(KDGanttViewItem*)) );
71 connect( mGantt, TQ_SIGNAL(gvItemMoved(KDGanttViewItem*)),
72 TQ_SLOT(itemMoved(KDGanttViewItem*)) );
73 connect( mGantt, TQ_SIGNAL(rescaling(KDGanttView::Scale)),
74 TQ_SLOT(overscale(KDGanttView::Scale)) );
75 connect( mGantt, TQ_SIGNAL( dateTimeDoubleClicked( const TQDateTime& ) ),
76 TQ_SLOT( newEventWithHint( const TQDateTime& ) ) );
77}
78
79KOTimelineView::~KOTimelineView()
80{
81 delete mEventPopup;
82}
83
84/*virtual*/
86{
88}
89
90/*virtual*/
92{
93 return KCal::DateList();
94}
95
96/*virtual*/
98{
99 return 0;
100}
101
102/*virtual*/
103void KOTimelineView::showDates(const TQDate& start, const TQDate& end)
104{
105 mStartDate = start;
106 mEndDate = end;
107 mHintDate = TQDateTime();
108 mGantt->setHorizonStart( TQDateTime(start) );
109 mGantt->setHorizonEnd( TQDateTime(end.addDays(1)) );
110 mGantt->setMinorScaleCount( 1 );
111 mGantt->setScale( KDGanttView::Hour );
112 mGantt->setMinimumScale( KDGanttView::Hour );
113 mGantt->setMaximumScale( KDGanttView::Hour );
114 mGantt->zoomToFit();
115
116 mGantt->setUpdateEnabled( false );
117 mGantt->clear();
118
119 // item for every calendar
120 TimelineItem *item = 0;
121 CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
122 if ( !calres ) {
123 item = new TimelineItem( i18n("Calendar"), calendar(), mGantt );
124 mCalendarItemMap[0][TQString()] = item;
125 } else {
126 CalendarResourceManager *manager = calres->resourceManager();
127 for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) {
128 TQColor resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
129 if ( (*it)->canHaveSubresources() ) {
130 TQStringList subResources = (*it)->subresources();
131 for ( TQStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) {
132 TQString type = (*it)->subresourceType( *subit );
133 if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") )
134 continue;
135 item = new TimelineItem( (*it)->labelForSubresource( *subit ), calendar(), mGantt );
136 resourceColor = *KOPrefs::instance()->resourceColor( (*it)->identifier() );
137 TQColor subrescol = *KOPrefs::instance()->resourceColor( *subit );
138 if ( subrescol.isValid() )
139 resourceColor = subrescol;
140 if ( resourceColor.isValid() )
141 item->setColors( resourceColor, resourceColor, resourceColor );
142 mCalendarItemMap[*it][*subit] = item;
143 }
144 } else {
145 item = new TimelineItem( (*it)->resourceName(), calendar(), mGantt );
146 if ( resourceColor.isValid() )
147 item->setColors( resourceColor, resourceColor, resourceColor );
148 mCalendarItemMap[*it][TQString()] = item;
149 }
150 }
151 }
152
153 // add incidences
154 Event::List events;
155 for ( TQDate day = start; day <= end; day = day.addDays( 1 ) ) {
157 for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) {
158 insertIncidence( *it, day );
159 }
160 }
161
162 mGantt->setUpdateEnabled( true );
163}
164
165/*virtual*/
166void KOTimelineView::showIncidences(const KCal::ListBase<KCal::Incidence>&, const TQDate &)
167{
168}
169
170/*virtual*/
172{
173 if ( mStartDate.isValid() && mEndDate.isValid() )
174 showDates( mStartDate, mEndDate );
175}
176
177/*virtual*/
179{
180 kdDebug() << k_funcinfo << incidence << " " << mode << endl;
181 switch ( mode ) {
182 case KOGlobals::INCIDENCEADDED:
183 insertIncidence( incidence );
184 break;
185 case KOGlobals::INCIDENCEEDITED:
186 removeIncidence( incidence );
187 insertIncidence( incidence );
188 break;
189 case KOGlobals::INCIDENCEDELETED:
190 removeIncidence( incidence );
191 break;
192 default:
193 updateView();
194 }
195}
196
197void KOTimelineView::itemSelected( KDGanttViewItem *item )
198{
199 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
200 if ( tlitem )
201 emit incidenceSelected( tlitem->incidence(), tlitem->originalStart().date() );
202}
203
204void KOTimelineView::itemDoubleClicked( KDGanttViewItem *item )
205{
206 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
207 if ( tlitem ) {
208 emit editIncidenceSignal( tlitem->incidence(), TQDate() );
209 }
210}
211
212void KOTimelineView::itemRightClicked( KDGanttViewItem *item )
213{
214 mHintDate = mGantt->getDateTimeForCoordX( TQCursor::pos().x(), true );
215 TimelineSubItem *tlitem = dynamic_cast<TimelineSubItem*>( item );
216 if ( !tlitem ) {
217 showNewEventPopup();
218 return;
219 }
220 if ( !mEventPopup )
221 mEventPopup = eventPopup();
222 mEventPopup->showIncidencePopup( calendar(), tlitem->incidence(), TQDate() );
223}
224
225bool KOTimelineView::eventDurationHint(TQDateTime & startDt, TQDateTime & endDt, bool & allDay)
226{
227 startDt = mHintDate;
228 endDt = mHintDate.addSecs( 2 * 60 * 60 );
229 allDay = false;
230 return mHintDate.isValid();
231}
232
233//slot
234void KOTimelineView::newEventWithHint( const TQDateTime& dt )
235{
236 mHintDate = dt;
237 emit newEventSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, dt );
238}
239
240TimelineItem * KOTimelineView::calendarItemForIncidence(KCal::Incidence * incidence)
241{
242 CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
243 TimelineItem *item = 0;
244 if ( !calres ) {
245 item = mCalendarItemMap[0][TQString()];
246 } else {
247 ResourceCalendar *res = calres->resource( incidence );
248 if ( !res )
249 return 0;
250 if ( res->canHaveSubresources() ) {
251 TQString subRes = res->subresourceIdentifier( incidence );
252 item = mCalendarItemMap[res][subRes];
253 } else {
254 item = mCalendarItemMap[res][TQString()];
255 }
256 }
257 return item;
258}
259
260void KOTimelineView::insertIncidence(KCal::Incidence * incidence, const TQDate &day )
261{
262 TimelineItem *item = calendarItemForIncidence( incidence );
263 if ( !item ) {
264 kdWarning() << k_funcinfo << "Help! Something is really wrong here!" << endl;
265 return;
266 }
267
268 if ( incidence->doesRecur() ) {
269 TQValueList<TQDateTime> l = incidence->startDateTimesForDate( day );
270 if ( l.isEmpty() ) {
271 // strange, but seems to happen for some recurring events...
272 item->insertIncidence( incidence, TQDateTime( day, incidence->dtStart().time() ),
273 TQDateTime( day, incidence->dtEnd().time() ) );
274 } else {
275 for ( TQValueList<TQDateTime>::ConstIterator it = l.constBegin();
276 it != l.constEnd(); ++it ) {
277 item->insertIncidence( incidence, *it, incidence->endDateForStart( *it ) );
278 }
279 }
280 } else {
281 if ( incidence->dtStart().date() == day || incidence->dtStart().date() < mStartDate )
282 item->insertIncidence( incidence );
283 }
284}
285
286void KOTimelineView::insertIncidence(KCal::Incidence * incidence)
287{
288 KCal::Event *event = dynamic_cast<KCal::Event*>( incidence );
289 if ( !event )
290 return;
291 if ( incidence->doesRecur() )
292 insertIncidence( incidence, TQDate() );
293 for ( TQDate day = mStartDate; day <= mEndDate; day = day.addDays( 1 ) ) {
294 Event::List events = calendar()->events( day, EventSortStartDate, SortDirectionAscending );
295 for ( Event::List::ConstIterator it = events.constBegin(); it != events.constEnd(); ++it ) {
296 if ( events.contains( event ) )
297 insertIncidence( *it, day );
298 }
299 }
300}
301
302void KOTimelineView::removeIncidence(KCal::Incidence * incidence)
303{
304 TimelineItem *item = calendarItemForIncidence( incidence );
305 if ( item ) {
306 item->removeIncidence( incidence );
307 } else {
308 // try harder, the incidence might already be removed from the resource
309 typedef TQMap<TQString, KOrg::TimelineItem*> M2_t;
310 typedef TQMap<KCal::ResourceCalendar*, M2_t> M1_t;
311 for ( M1_t::ConstIterator it1 = mCalendarItemMap.constBegin(); it1 != mCalendarItemMap.constEnd(); ++it1 ) {
312 for ( M2_t::ConstIterator it2 = it1.data().constBegin(); it2 != it1.data().constEnd(); ++it2 ) {
313 if ( it2.data() ) {
314 it2.data()->removeIncidence( incidence );
315 }
316 }
317 }
318 }
319}
320
321void KOTimelineView::itemMoved(KDGanttViewItem * item)
322{
323 TimelineSubItem *tlit = dynamic_cast<TimelineSubItem*>( item );
324 if ( !tlit )
325 return;
326 Incidence *i = tlit->incidence();
327 mChanger->beginChange( i, 0, TQString() );
328 TQDateTime newStart = tlit->startTime();
329 if ( i->doesFloat() )
330 newStart = TQDateTime( newStart.date() );
331 int delta = tlit->originalStart().secsTo( newStart );
332 i->setDtStart( i->dtStart().addSecs( delta ) );
333 int duration = tlit->startTime().secsTo( tlit->endTime() );
334 int allDayOffset = 0;
335 if ( i->doesFloat() ) {
336 duration /= (60*60*24);
337 duration *= (60*60*24);
338 allDayOffset = (60*60*24);
339 duration -= allDayOffset;
340 if ( duration < 0 ) duration = 0;
341 }
342 i->setDuration( duration );
343 TimelineItem *parent = static_cast<TimelineItem*>( tlit->parent() );
344 parent->moveItems( i, tlit->originalStart().secsTo( newStart ), duration + allDayOffset );
345 mChanger->endChange( i, 0, TQString() );
346}
347
348void KOTimelineView::overscale(KDGanttView::Scale scale)
349{
350 Q_UNUSED( scale );
351 mGantt->setZoomFactor( 1, false );
352 mGantt->setScale( KDGanttView::Hour );
353 mGantt->setMinorScaleCount( 12 );
354}
355
356#include "kotimelineview.moc"
ResourceCalendar * resource(Incidence *incidence)
CalendarResourceManager * resourceManager() const
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Incidence * incidence(const TQString &uid)
bool doesFloat() const
virtual TQDateTime dtStart() const
virtual TQDateTime dtEnd() const
bool doesRecur() const
virtual void setDtStart(const TQDateTime &dtStart)
virtual TQValueList< TQDateTime > startDateTimesForDate(const TQDate &date) const
virtual TQDateTime endDateForStart(const TQDateTime &startDt) const
virtual TQString subresourceIdentifier(Incidence *incidence)
virtual bool canHaveSubresources() const
KOEventView is the abstract base class from which all other calendar views for event data are derived...
Definition: koeventview.h:56
KOEventPopupMenu * eventPopup()
Construct a standard context menu for an event.
Definition: koeventview.cpp:60
virtual void showDates(const TQDate &, const TQDate &)
Show incidences for the given date range.
virtual KCal::ListBase< KCal::Incidence > selectedIncidences()
virtual bool eventDurationHint(TQDateTime &startDt, TQDateTime &endDt, bool &allDay)
Set the default start/end date/time for new events.
virtual void updateView()
Updates the current display to reflect changes that may have happened in the calendar since the last ...
virtual KCal::DateList selectedIncidenceDates()
virtual int currentDateCount()
Return number of currently shown dates.
virtual void changeIncidenceDisplay(KCal::Incidence *incidence, int mode)
Updates the current display to reflect the changes to one particular incidence.
virtual Calendar * calendar()
Return calendar object of this view.
Definition: baseview.h:89
void editIncidenceSignal(Incidence *, const TQDate &)
instructs the receiver to begin editing the incidence specified in some manner.
void newEventSignal(ResourceCalendar *res, const TQString &subResource)
instructs the receiver to create a new event.
EventSortStartDate
SortDirectionAscending