KCal Library
dndfactory.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the kcal library. 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 Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net> 00008 Copyright (c) 2008 Thomas Thrainer <tom_t@gmx.at> 00009 00010 This library is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU Library General Public 00012 License as published by the Free Software Foundation; either 00013 version 2 of the License, or (at your option) any later version. 00014 00015 This library is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 Library General Public License for more details. 00019 00020 You should have received a copy of the GNU Library General Public License 00021 along with this library; see the file COPYING.LIB. If not, write to 00022 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00023 Boston, MA 02110-1301, USA. 00024 */ 00038 #include "dndfactory.h" 00039 #include "vcaldrag.h" 00040 #include "icaldrag.h" 00041 #include "calendar.h" 00042 #include "calendarlocal.h" 00043 00044 #include <kiconloader.h> 00045 #include <kdebug.h> 00046 #include <klocale.h> 00047 #include <kurl.h> 00048 00049 #include <QtGui/QApplication> 00050 #include <QtGui/QClipboard> 00051 #include <QtGui/QDropEvent> 00052 #include <QtGui/QPixmap> 00053 00054 using namespace KCal; 00055 00060 //@cond PRIVATE 00061 class KCal::DndFactory::Private 00062 { 00063 public: 00064 Private( Calendar *cal ) 00065 : mCalendar ( cal ) 00066 {} 00067 00068 Incidence * pasteIncidence( Incidence *inc, 00069 const QDate &newDate, 00070 const QTime *newTime = 0 ) 00071 { 00072 if ( inc ) { 00073 inc = inc->clone(); 00074 inc->recreate(); 00075 } 00076 00077 if ( inc && newDate.isValid() ) { 00078 if ( inc->type() == "Event" ) { 00079 00080 Event *anEvent = static_cast<Event*>( inc ); 00081 // Calculate length of event 00082 int daysOffset = anEvent->dtStart().date().daysTo( 00083 anEvent->dtEnd().date() ); 00084 // new end date if event starts at the same time on the new day 00085 KDateTime endDate( anEvent->dtEnd() ); 00086 endDate.setDate( newDate.addDays( daysOffset ) ); 00087 00088 KDateTime startDate( anEvent->dtStart() ); 00089 startDate.setDate( newDate ); 00090 if ( newTime ) { 00091 // additional offset for new time of day 00092 int addSecsOffset( anEvent->dtStart().time().secsTo( *newTime ) ); 00093 endDate=endDate.addSecs( addSecsOffset ); 00094 startDate.setTime( *newTime ); 00095 } 00096 anEvent->setDtStart( startDate ); 00097 anEvent->setDtEnd( endDate ); 00098 00099 } else if ( inc->type() == "Todo" ) { 00100 Todo *anTodo = static_cast<Todo*>( inc ); 00101 KDateTime dueDate( anTodo->dtDue() ); 00102 dueDate.setDate( newDate ); 00103 if ( newTime ) { 00104 dueDate.setTime( *newTime ); 00105 } 00106 anTodo->setDtDue( dueDate ); 00107 } else if ( inc->type() == "Journal" ) { 00108 Journal *anJournal = static_cast<Journal*>( inc ); 00109 KDateTime startDate( anJournal->dtStart() ); 00110 startDate.setDate( newDate ); 00111 if ( newTime ) { 00112 startDate.setTime( *newTime ); 00113 } else { 00114 startDate.setTime( QTime( 0, 0, 0 ) ); 00115 } 00116 anJournal->setDtStart( startDate ); 00117 } else { 00118 kDebug() << "Trying to paste unknown incidence of type" << inc->type(); 00119 } 00120 } 00121 00122 return inc; 00123 } 00124 00125 Calendar *mCalendar; 00126 }; 00127 //@endcond 00128 00129 DndFactory::DndFactory( Calendar *cal ) 00130 : d( new KCal::DndFactory::Private ( cal ) ) 00131 { 00132 } 00133 00134 DndFactory::~DndFactory() 00135 { 00136 delete d; 00137 } 00138 00139 QMimeData *DndFactory::createMimeData() 00140 { 00141 QMimeData *mimeData = new QMimeData; 00142 00143 ICalDrag::populateMimeData( mimeData, d->mCalendar ); 00144 VCalDrag::populateMimeData( mimeData, d->mCalendar ); 00145 00146 return mimeData; 00147 } 00148 00149 QDrag *DndFactory::createDrag( QWidget *owner ) 00150 { 00151 QDrag *drag = new QDrag( owner ); 00152 drag->setMimeData( createMimeData() ); 00153 00154 return drag; 00155 } 00156 00157 QMimeData *DndFactory::createMimeData( Incidence *incidence ) 00158 { 00159 CalendarLocal cal( d->mCalendar->timeSpec() ); 00160 Incidence *i = incidence->clone(); 00161 cal.addIncidence( i ); 00162 00163 QMimeData *mimeData = new QMimeData; 00164 00165 ICalDrag::populateMimeData( mimeData, &cal ); 00166 VCalDrag::populateMimeData( mimeData, &cal ); 00167 00168 KUrl uri = i->uri(); 00169 if ( uri.isValid() ) { 00170 QMap<QString, QString> metadata; 00171 metadata["labels"] = KUrl::toPercentEncoding( i->summary() ); 00172 uri.populateMimeData( mimeData, metadata ); 00173 } 00174 00175 return mimeData; 00176 } 00177 00178 QDrag *DndFactory::createDrag( Incidence *incidence, QWidget *owner ) 00179 { 00180 QDrag *drag = new QDrag( owner ); 00181 drag->setMimeData( createMimeData( incidence ) ); 00182 00183 if ( incidence->type() == "Event" ) { 00184 drag->setPixmap( BarIcon( "view-calendar-day" ) ); 00185 } else if ( incidence->type() == "Todo" ) { 00186 drag->setPixmap( BarIcon( "view-calendar-tasks" ) ); 00187 } 00188 00189 return drag; 00190 } 00191 00192 Calendar *DndFactory::createDropCalendar( const QMimeData *md ) 00193 { 00194 return createDropCalendar( md, d->mCalendar->timeSpec() ); 00195 } 00196 00197 Calendar *DndFactory::createDropCalendar( const QMimeData *md, const KDateTime::Spec &timeSpec ) 00198 { 00199 Calendar *cal = new CalendarLocal( timeSpec ); 00200 00201 if ( ICalDrag::fromMimeData( md, cal ) || 00202 VCalDrag::fromMimeData( md, cal ) ){ 00203 return cal; 00204 } 00205 delete cal; 00206 return 0; 00207 } 00208 00209 Calendar *DndFactory::createDropCalendar( QDropEvent *de ) 00210 { 00211 Calendar *cal = createDropCalendar( de->mimeData() ); 00212 if ( cal ) { 00213 de->accept(); 00214 return cal; 00215 } 00216 return 0; 00217 } 00218 00219 Event *DndFactory::createDropEvent( const QMimeData *md ) 00220 { 00221 kDebug(); 00222 Event *ev = 0; 00223 Calendar *cal = createDropCalendar( md ); 00224 00225 if ( cal ) { 00226 Event::List events = cal->events(); 00227 if ( !events.isEmpty() ) { 00228 ev = new Event( *events.first() ); 00229 } 00230 delete cal; 00231 } 00232 return ev; 00233 } 00234 00235 Event *DndFactory::createDropEvent( QDropEvent *de ) 00236 { 00237 Event *ev = createDropEvent( de->mimeData() ); 00238 00239 if ( ev ) { 00240 de->accept(); 00241 } 00242 00243 return ev; 00244 } 00245 00246 Todo *DndFactory::createDropTodo( const QMimeData *md ) 00247 { 00248 kDebug(); 00249 Todo *todo = 0; 00250 Calendar *cal = createDropCalendar( md ); 00251 00252 if ( cal ) { 00253 Todo::List todos = cal->todos(); 00254 if ( !todos.isEmpty() ) { 00255 todo = new Todo( *todos.first() ); 00256 } 00257 delete cal; 00258 } 00259 00260 return todo; 00261 } 00262 00263 Todo *DndFactory::createDropTodo( QDropEvent *de ) 00264 { 00265 Todo *todo = createDropTodo( de->mimeData() ); 00266 00267 if ( todo ) { 00268 de->accept(); 00269 } 00270 00271 return todo; 00272 } 00273 00274 void DndFactory::cutIncidence( Incidence *selectedInc ) 00275 { 00276 Incidence::List list; 00277 list.append( selectedInc ); 00278 cutIncidences( list ); 00279 } 00280 00281 bool DndFactory::cutIncidences( const Incidence::List &incidences ) 00282 { 00283 if ( copyIncidences( incidences ) ) { 00284 Incidence::List::ConstIterator it; 00285 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00286 d->mCalendar->deleteIncidence( *it ); 00287 } 00288 return true; 00289 } else { 00290 return false; 00291 } 00292 } 00293 00294 bool DndFactory::copyIncidences( const Incidence::List &incidences ) 00295 { 00296 QClipboard *cb = QApplication::clipboard(); 00297 CalendarLocal cal( d->mCalendar->timeSpec() ); 00298 00299 Incidence::List::ConstIterator it; 00300 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00301 if ( *it ) { 00302 cal.addIncidence( ( *it )->clone() ); 00303 } 00304 } 00305 00306 QMimeData *mimeData = new QMimeData; 00307 00308 ICalDrag::populateMimeData( mimeData, &cal ); 00309 VCalDrag::populateMimeData( mimeData, &cal ); 00310 00311 if ( cal.incidences().isEmpty() ) { 00312 return false; 00313 } else { 00314 cb->setMimeData( mimeData ); 00315 return true; 00316 } 00317 } 00318 00319 bool DndFactory::copyIncidence( Incidence *selectedInc ) 00320 { 00321 Incidence::List list; 00322 list.append( selectedInc ); 00323 return copyIncidences( list ); 00324 } 00325 00326 Incidence::List DndFactory::pasteIncidences( const QDate &newDate, 00327 const QTime *newTime ) 00328 { 00329 QClipboard *cb = QApplication::clipboard(); 00330 Calendar *cal = createDropCalendar( cb->mimeData() ); 00331 Incidence::List list; 00332 00333 if ( !cal ) { 00334 kDebug() << "Can't parse clipboard"; 00335 return list; 00336 } 00337 00338 // All pasted incidences get new uids, must keep track of old uids, 00339 // so we can update child's parents 00340 QHash<QString,Incidence*> oldUidToNewInc; 00341 00342 Incidence::List::ConstIterator it; 00343 const Incidence::List incs = cal->incidences(); 00344 for ( it = incs.constBegin(); 00345 it != incs.constEnd(); ++it ) { 00346 Incidence *inc = d->pasteIncidence( *it, newDate, newTime ); 00347 if ( inc ) { 00348 list.append( inc ); 00349 oldUidToNewInc[( *it )->uid()] = inc; 00350 } 00351 } 00352 00353 // update relations 00354 for ( it = list.constBegin(); it != list.constEnd(); ++it ) { 00355 Incidence *inc = *it; 00356 if ( oldUidToNewInc.contains( inc->relatedToUid() ) ) { 00357 Incidence *parentInc = oldUidToNewInc[inc->relatedToUid()]; 00358 inc->setRelatedToUid( parentInc->uid() ); 00359 inc->setRelatedTo( parentInc ); 00360 } else { 00361 // not related to anything in the clipboard 00362 inc->setRelatedToUid( QString() ); 00363 inc->setRelatedTo( 0 ); 00364 } 00365 } 00366 00367 return list; 00368 } 00369 00370 Incidence *DndFactory::pasteIncidence( const QDate &newDate, const QTime *newTime ) 00371 { 00372 QClipboard *cb = QApplication::clipboard(); 00373 Calendar *cal = createDropCalendar( cb->mimeData() ); 00374 00375 if ( !cal ) { 00376 kDebug() << "Can't parse clipboard"; 00377 return 0; 00378 } 00379 00380 Incidence::List incList = cal->incidences(); 00381 Incidence *inc = incList.isEmpty() ? 0 : incList.first(); 00382 00383 Incidence *newInc = d->pasteIncidence( inc, newDate, newTime ); 00384 newInc->setRelatedTo( 0 ); 00385 return newInc; 00386 }