libkcal

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 <tdemessagebox.h>
00031 #include <tdelocale.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 }