dndfactory.cpp
00001 /* 00002 This file is part of libkcal. 00003 00004 Copyright (c) 1998 Preston Brown <pbrown@kde.org> 00005 Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org> 00006 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #include <tqapplication.h> 00025 #include <tqclipboard.h> 00026 #include <tqmap.h> 00027 00028 #include <kiconloader.h> 00029 #include <kdebug.h> 00030 #include <kmessagebox.h> 00031 #include <klocale.h> 00032 00033 #include "vcaldrag.h" 00034 #include "icaldrag.h" 00035 #include "calendar.h" 00036 #include "vcalformat.h" 00037 #include "icalformat.h" 00038 #include "calendarlocal.h" 00039 00040 #include "dndfactory.h" 00041 00042 using namespace KCal; 00043 00044 class DndFactory::Private 00045 { 00046 public: 00047 Incidence * pasteIncidence( Incidence *inc, 00048 const TQDate &newDate, 00049 const TQTime *newTime = 0 ) 00050 { 00051 if ( inc ) { 00052 inc = inc->clone(); 00053 inc->recreate(); 00054 } 00055 00056 if ( inc && newDate.isValid() ) { 00057 if ( inc->type() == "Event" ) { 00058 Event *anEvent = static_cast<Event*>( inc ); 00059 // Calculate length of event 00060 int daysOffset = anEvent->dtStart().date().daysTo( 00061 anEvent->dtEnd().date() ); 00062 // new end date if event starts at the same time on the new day 00063 TQDateTime endDate( newDate.addDays(daysOffset), anEvent->dtEnd().time() ); 00064 00065 if ( newTime ) { 00066 // additional offset for new time of day 00067 int addSecsOffset( anEvent->dtStart().time().secsTo( *newTime )); 00068 endDate=endDate.addSecs( addSecsOffset ); 00069 anEvent->setDtStart( TQDateTime( newDate, *newTime ) ); 00070 } else { 00071 anEvent->setDtStart( TQDateTime( newDate, anEvent->dtStart().time() ) ); 00072 } 00073 anEvent->setDtEnd( endDate ); 00074 } else if ( inc->type() == "Todo" ) { 00075 Todo *anTodo = static_cast<Todo*>( inc ); 00076 if ( newTime ) { 00077 anTodo->setDtDue( TQDateTime( newDate, *newTime ) ); 00078 } else { 00079 anTodo->setDtDue( TQDateTime( newDate, anTodo->dtDue().time() ) ); 00080 } 00081 } else if ( inc->type() == "Journal" ) { 00082 Journal *anJournal = static_cast<Journal*>( inc ); 00083 if ( newTime ) { 00084 anJournal->setDtStart( TQDateTime( newDate, *newTime ) ); 00085 } else { 00086 anJournal->setDtStart( TQDateTime( newDate ) ); 00087 } 00088 } else { 00089 kdDebug(5850) << "Trying to paste unknown incidence of type " << inc->type() << endl; 00090 } 00091 } 00092 return inc; 00093 } 00094 }; 00095 00096 DndFactory::DndFactory( Calendar *cal ) : 00097 mCalendar( cal ), d( new Private ) 00098 { 00099 } 00100 00101 DndFactory::~DndFactory() 00102 { 00103 delete d; 00104 } 00105 00106 ICalDrag *DndFactory::createDrag( Incidence *incidence, TQWidget *owner ) 00107 { 00108 CalendarLocal cal( mCalendar->timeZoneId() ); 00109 Incidence *i = incidence->clone(); 00110 cal.addIncidence( i ); 00111 00112 ICalDrag *icd = new ICalDrag( &cal, owner ); 00113 if ( i->type() == "Event" ) 00114 icd->setPixmap( BarIcon( "appointment" ) ); 00115 else if ( i->type() == "Todo" ) 00116 icd->setPixmap( BarIcon( "todo" ) ); 00117 00118 return icd; 00119 } 00120 00121 Event *DndFactory::createDrop(TQDropEvent *de) 00122 { 00123 kdDebug(5800) << "DndFactory::createDrop()" << endl; 00124 00125 CalendarLocal cal( mCalendar->timeZoneId() ); 00126 00127 if ( ICalDrag::decode( de, &cal ) || VCalDrag::decode( de, &cal ) ) { 00128 de->accept(); 00129 00130 Event::List events = cal.events(); 00131 if ( !events.isEmpty() ) { 00132 Event *event = new Event( *events.first() ); 00133 return event; 00134 } 00135 } 00136 00137 return 0; 00138 } 00139 00140 Todo *DndFactory::createDropTodo(TQDropEvent *de) 00141 { 00142 kdDebug(5800) << "VCalFormat::createDropTodo()" << endl; 00143 00144 CalendarLocal cal( mCalendar->timeZoneId() ); 00145 00146 if ( ICalDrag::decode( de, &cal ) || VCalDrag::decode( de, &cal ) ) { 00147 de->accept(); 00148 00149 Todo::List todos = cal.todos(); 00150 if ( !todos.isEmpty() ) { 00151 Todo *todo = new Todo( *todos.first() ); 00152 return todo; 00153 } 00154 } 00155 00156 return 0; 00157 } 00158 00159 void DndFactory::cutIncidence( Incidence *selectedInc ) 00160 { 00161 Incidence::List list; 00162 list.append( selectedInc ); 00163 cutIncidences( list ); 00164 } 00165 00166 bool DndFactory::cutIncidences( const Incidence::List &incidences ) 00167 { 00168 if ( copyIncidences( incidences ) ) { 00169 Incidence::List::ConstIterator it; 00170 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00171 mCalendar->deleteIncidence( *it ); 00172 } 00173 return true; 00174 } else { 00175 return false; 00176 } 00177 } 00178 00179 bool DndFactory::copyIncidences( const Incidence::List &incidences ) 00180 { 00181 TQClipboard *cb = TQApplication::clipboard(); 00182 CalendarLocal cal( mCalendar->timeZoneId() ); 00183 Incidence::List::ConstIterator it; 00184 00185 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00186 if ( *it ) { 00187 cal.addIncidence( ( *it )->clone() ); 00188 } 00189 } 00190 00191 if ( cal.incidences().isEmpty() ) { 00192 return false; 00193 } else { 00194 cb->setData( new ICalDrag( &cal ) ); 00195 return true; 00196 } 00197 } 00198 00199 bool DndFactory::copyIncidence( Incidence *selectedInc ) 00200 { 00201 Incidence::List list; 00202 list.append( selectedInc ); 00203 return copyIncidences( list ); 00204 } 00205 00206 Incidence::List DndFactory::pasteIncidences( const TQDate &newDate, const TQTime *newTime ) 00207 { 00208 CalendarLocal cal( mCalendar->timeZoneId() ); 00209 TQClipboard *cb = TQApplication::clipboard(); 00210 Incidence::List list; 00211 00212 if ( !ICalDrag::decode( cb->data(), &cal ) && 00213 !VCalDrag::decode( cb->data(), &cal ) ) { 00214 kdDebug(5800) << "Can't parse clipboard" << endl; 00215 return list; 00216 } 00217 00218 // All pasted incidences get new uids, must keep track of old uids, 00219 // so we can update child's parents 00220 TQMap<TQString,Incidence*> oldUidToNewInc; 00221 00222 Incidence::List::ConstIterator it; 00223 const Incidence::List incs = cal.incidences(); 00224 for ( it = incs.constBegin(); it != incs.constEnd(); ++it ) { 00225 Incidence *inc = d->pasteIncidence( *it, newDate, newTime ); 00226 if ( inc ) { 00227 list.append( inc ); 00228 oldUidToNewInc[( *it )->uid()] = inc; 00229 } 00230 } 00231 00232 // update relations 00233 for ( it = list.constBegin(); it != list.constEnd(); ++it ) { 00234 Incidence *inc = *it; 00235 if ( oldUidToNewInc.contains( inc->relatedToUid() ) ) { 00236 Incidence *parentInc = oldUidToNewInc[inc->relatedToUid()]; 00237 inc->setRelatedToUid( parentInc->uid() ); 00238 inc->setRelatedTo( parentInc ); 00239 } else { 00240 // not related to anything in the clipboard 00241 inc->setRelatedToUid( TQString() ); 00242 inc->setRelatedTo( 0 ); 00243 } 00244 } 00245 00246 return list; 00247 } 00248 00249 Incidence *DndFactory::pasteIncidence( const TQDate &newDate, const TQTime *newTime ) 00250 { 00251 CalendarLocal cal( mCalendar->timeZoneId() ); 00252 TQClipboard *cb = TQApplication::clipboard(); 00253 00254 if ( !ICalDrag::decode( cb->data(), &cal ) && 00255 !VCalDrag::decode( cb->data(), &cal ) ) { 00256 kdDebug(5800) << "Can't parse clipboard" << endl; 00257 return 0; 00258 } 00259 00260 Incidence::List incList = cal.incidences(); 00261 Incidence *inc = incList.isEmpty() ? 0 : incList.first(); 00262 00263 Incidence *newInc = d->pasteIncidence( inc, newDate, newTime ); 00264 newInc->setRelatedTo( 0 ); 00265 return newInc; 00266 }