KCalUtils Library
dndfactory.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the kcalutils 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 */ 00037 #include "dndfactory.h" 00038 #include "icaldrag.h" 00039 #include "vcaldrag.h" 00040 00041 #include <KDebug> 00042 #include <KIconLoader> // for BarIcon 00043 #include <KUrl> 00044 00045 #include <QtCore/QMimeData> 00046 #include <QtGui/QApplication> 00047 #include <QtGui/QClipboard> 00048 #include <QtGui/QDrag> 00049 #include <QtGui/QDropEvent> 00050 #include <QtGui/QPixmap> 00051 00052 using namespace KCalCore; 00053 using namespace KCalUtils; 00054 00059 //@cond PRIVATE 00060 class KCalUtils::DndFactory::Private 00061 { 00062 public: 00063 Private( const MemoryCalendar::Ptr &cal ) 00064 : mCalendar ( cal ) 00065 {} 00066 00067 Incidence::Ptr pasteIncidence( const Incidence::Ptr &incidence, 00068 const KDateTime &newDateTime, 00069 const QFlags<PasteFlag> &pasteOptions ) 00070 { 00071 00072 Incidence::Ptr inc( incidence ); 00073 00074 if ( inc ) { 00075 inc = Incidence::Ptr( inc->clone() ); 00076 inc->recreate(); 00077 } 00078 00079 if ( inc && newDateTime.isValid() ) { 00080 if ( inc->type() == Incidence::TypeEvent ) { 00081 00082 Event::Ptr event = inc.staticCast<Event>(); 00083 00084 // in seconds 00085 const int durationInSeconds = event->dtStart().secsTo( event->dtEnd() ); 00086 const int durationInDays = event->dtStart().daysTo( event->dtEnd() ); 00087 00088 event->setDtStart( newDateTime ); 00089 00090 if ( newDateTime.isDateOnly() ) { 00091 event->setDtEnd( newDateTime.addDays( durationInDays ) ); 00092 } else { 00093 event->setDtEnd( newDateTime.addSecs( durationInSeconds ) ); 00094 } 00095 00096 } else if ( inc->type() == Incidence::TypeTodo ) { 00097 Todo::Ptr aTodo = inc.staticCast<Todo>(); 00098 00099 if ( pasteOptions & FlagTodosPasteAtDtStart ) { 00100 aTodo->setDtStart( newDateTime ); 00101 } else { 00102 aTodo->setDtDue( newDateTime ); 00103 } 00104 00105 } else if ( inc->type() == Incidence::TypeJournal ) { 00106 inc->setDtStart( newDateTime ); 00107 } else { 00108 kDebug() << "Trying to paste unknown incidence of type" << int( inc->type() ); 00109 } 00110 } 00111 00112 return inc; 00113 } 00114 00115 MemoryCalendar::Ptr mCalendar; 00116 }; 00117 //@endcond 00118 00119 DndFactory::DndFactory( const MemoryCalendar::Ptr &cal ) 00120 : d( new KCalUtils::DndFactory::Private ( cal ) ) 00121 { 00122 } 00123 00124 DndFactory::~DndFactory() 00125 { 00126 delete d; 00127 } 00128 00129 QMimeData *DndFactory::createMimeData() 00130 { 00131 QMimeData *mimeData = new QMimeData; 00132 00133 ICalDrag::populateMimeData( mimeData, d->mCalendar ); 00134 VCalDrag::populateMimeData( mimeData, d->mCalendar ); 00135 00136 return mimeData; 00137 } 00138 00139 QDrag *DndFactory::createDrag( QWidget *owner ) 00140 { 00141 QDrag *drag = new QDrag( owner ); 00142 drag->setMimeData( createMimeData() ); 00143 00144 return drag; 00145 } 00146 00147 QMimeData *DndFactory::createMimeData( const Incidence::Ptr &incidence ) 00148 { 00149 MemoryCalendar::Ptr cal( new MemoryCalendar( d->mCalendar->timeSpec() ) ); 00150 Incidence::Ptr i( incidence->clone() ); 00151 cal->addIncidence( i ); 00152 00153 QMimeData *mimeData = new QMimeData; 00154 00155 ICalDrag::populateMimeData( mimeData, cal ); 00156 VCalDrag::populateMimeData( mimeData, cal ); 00157 00158 KUrl uri = i->uri(); 00159 if ( uri.isValid() ) { 00160 QMap<QString, QString> metadata; 00161 metadata["labels"] = KUrl::toPercentEncoding( i->summary() ); 00162 uri.populateMimeData( mimeData, metadata ); 00163 } 00164 00165 return mimeData; 00166 } 00167 00168 QDrag *DndFactory::createDrag( const Incidence::Ptr &incidence, QWidget *owner ) 00169 { 00170 QDrag *drag = new QDrag( owner ); 00171 drag->setMimeData( createMimeData( incidence ) ); 00172 drag->setPixmap( BarIcon( incidence->iconName() ) ); 00173 00174 return drag; 00175 } 00176 00177 MemoryCalendar::Ptr DndFactory::createDropCalendar( const QMimeData *md ) 00178 { 00179 return createDropCalendar( md, d->mCalendar->timeSpec() ); 00180 } 00181 00182 MemoryCalendar::Ptr DndFactory::createDropCalendar( const QMimeData *md, 00183 const KDateTime::Spec &timeSpec ) 00184 { 00185 MemoryCalendar::Ptr cal( new MemoryCalendar( timeSpec ) ); 00186 00187 if ( ICalDrag::fromMimeData( md, cal ) || 00188 VCalDrag::fromMimeData( md, cal ) ){ 00189 return cal; 00190 } 00191 00192 return MemoryCalendar::Ptr(); 00193 } 00194 00195 MemoryCalendar::Ptr DndFactory::createDropCalendar( QDropEvent *de ) 00196 { 00197 MemoryCalendar::Ptr cal( createDropCalendar( de->mimeData() ) ); 00198 if ( cal ) { 00199 de->accept(); 00200 return cal; 00201 } 00202 return MemoryCalendar::Ptr(); 00203 } 00204 00205 Event::Ptr DndFactory::createDropEvent( const QMimeData *md ) 00206 { 00207 kDebug(); 00208 Event::Ptr ev; 00209 MemoryCalendar::Ptr cal( createDropCalendar( md ) ); 00210 00211 if ( cal ) { 00212 Event::List events = cal->events(); 00213 if ( !events.isEmpty() ) { 00214 ev = Event::Ptr( new Event( *events.first() ) ); 00215 } 00216 } 00217 return ev; 00218 } 00219 00220 Event::Ptr DndFactory::createDropEvent( QDropEvent *de ) 00221 { 00222 Event::Ptr ev = createDropEvent( de->mimeData() ); 00223 00224 if ( ev ) { 00225 de->accept(); 00226 } 00227 00228 return ev; 00229 } 00230 00231 Todo::Ptr DndFactory::createDropTodo( const QMimeData *md ) 00232 { 00233 kDebug(); 00234 Todo::Ptr todo; 00235 MemoryCalendar::Ptr cal( createDropCalendar( md ) ); 00236 00237 if ( cal ) { 00238 Todo::List todos = cal->todos(); 00239 if ( !todos.isEmpty() ) { 00240 todo = Todo::Ptr( new Todo( *todos.first() ) ); 00241 } 00242 } 00243 00244 return todo; 00245 } 00246 00247 Todo::Ptr DndFactory::createDropTodo( QDropEvent *de ) 00248 { 00249 Todo::Ptr todo = createDropTodo( de->mimeData() ); 00250 00251 if ( todo ) { 00252 de->accept(); 00253 } 00254 00255 return todo; 00256 } 00257 00258 void DndFactory::cutIncidence( const Incidence::Ptr &selectedInc ) 00259 { 00260 Incidence::List list; 00261 list.append( selectedInc ); 00262 cutIncidences( list ); 00263 } 00264 00265 bool DndFactory::cutIncidences( const Incidence::List &incidences ) 00266 { 00267 if ( copyIncidences( incidences ) ) { 00268 Incidence::List::ConstIterator it; 00269 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00270 d->mCalendar->deleteIncidence( *it ); 00271 } 00272 return true; 00273 } else { 00274 return false; 00275 } 00276 } 00277 00278 bool DndFactory::copyIncidences( const Incidence::List &incidences ) 00279 { 00280 QClipboard *cb = QApplication::clipboard(); 00281 MemoryCalendar::Ptr cal( new MemoryCalendar( d->mCalendar->timeSpec() ) ); 00282 00283 Incidence::List::ConstIterator it; 00284 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { 00285 if ( *it ) { 00286 cal->addIncidence( Incidence::Ptr( ( *it )->clone() ) ); 00287 } 00288 } 00289 00290 QMimeData *mimeData = new QMimeData; 00291 00292 ICalDrag::populateMimeData( mimeData, cal ); 00293 VCalDrag::populateMimeData( mimeData, cal ); 00294 00295 if ( cal->incidences().isEmpty() ) { 00296 return false; 00297 } else { 00298 cb->setMimeData( mimeData ); 00299 return true; 00300 } 00301 } 00302 00303 bool DndFactory::copyIncidence( const Incidence::Ptr &selectedInc ) 00304 { 00305 Incidence::List list; 00306 list.append( selectedInc ); 00307 return copyIncidences( list ); 00308 } 00309 00310 Incidence::List DndFactory::pasteIncidences( const KDateTime &newDateTime, 00311 const QFlags<PasteFlag> &pasteOptions ) 00312 { 00313 QClipboard *cb = QApplication::clipboard(); 00314 MemoryCalendar::Ptr cal( createDropCalendar( cb->mimeData() ) ); 00315 Incidence::List list; 00316 00317 if ( !cal ) { 00318 kDebug() << "Can't parse clipboard"; 00319 return list; 00320 } 00321 00322 // All pasted incidences get new uids, must keep track of old uids, 00323 // so we can update child's parents 00324 QHash<QString, Incidence::Ptr> oldUidToNewInc; 00325 00326 Incidence::List::ConstIterator it; 00327 const Incidence::List incs = cal->incidences(); 00328 for ( it = incs.constBegin(); 00329 it != incs.constEnd(); ++it ) { 00330 Incidence::Ptr inc = d->pasteIncidence( *it, newDateTime, pasteOptions ); 00331 if ( inc ) { 00332 list.append( inc ); 00333 oldUidToNewInc[(*it)->uid()] = *it; 00334 } 00335 } 00336 00337 // update relations 00338 for ( it = list.constBegin(); it != list.constEnd(); ++it ) { 00339 Incidence::Ptr inc = *it; 00340 if ( oldUidToNewInc.contains( inc->relatedTo() ) ) { 00341 Incidence::Ptr parentInc = oldUidToNewInc[inc->relatedTo()]; 00342 inc->setRelatedTo( parentInc->uid() ); 00343 } else { 00344 // not related to anything in the clipboard 00345 inc->setRelatedTo( QString() ); 00346 } 00347 } 00348 00349 return list; 00350 } 00351 00352 Incidence::Ptr DndFactory::pasteIncidence( const KDateTime &newDateTime, 00353 const QFlags<PasteFlag> &pasteOptions ) 00354 { 00355 QClipboard *cb = QApplication::clipboard(); 00356 MemoryCalendar::Ptr cal( createDropCalendar( cb->mimeData() ) ); 00357 00358 if ( !cal ) { 00359 kDebug() << "Can't parse clipboard"; 00360 return Incidence::Ptr(); 00361 } 00362 00363 Incidence::List incList = cal->incidences(); 00364 Incidence::Ptr inc = incList.isEmpty() ? Incidence::Ptr() : incList.first(); 00365 00366 return d->pasteIncidence( inc, newDateTime, pasteOptions ); 00367 }