summaryrefslogtreecommitdiff
path: root/kcalutils/dndfactory.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2012-06-27 07:49:37 (GMT)
committerChristian Mollekopf <chrigi_1@fastmail.fm>2012-06-27 07:49:37 (GMT)
commitf4a1668ab4aba34ab39c271527cdbaff8557b52c (patch)
treec7a4d190013958758c10170717002fd5b0f6e7aa /kcalutils/dndfactory.cpp
parent9fc556b238e0fbf12f7299439ee6b8953b975ffb (diff)
downloadlibcalendaring-f4a1668ab4aba34ab39c271527cdbaff8557b52c.tar.gz
initial import of kcalutils
commit 4fddf6f044ea74e348f1b4bf664c17c4d5236a29 Author: Allen Winter <allen.winter@kdab.com> Date: Sun Jun 24 18:33:17 2012 -0400 set version for 4.9rc1 release
Diffstat (limited to 'kcalutils/dndfactory.cpp')
-rw-r--r--kcalutils/dndfactory.cpp369
1 files changed, 369 insertions, 0 deletions
diff --git a/kcalutils/dndfactory.cpp b/kcalutils/dndfactory.cpp
new file mode 100644
index 0000000..745f49f
--- /dev/null
+++ b/kcalutils/dndfactory.cpp
@@ -0,0 +1,369 @@
+/*
+ This file is part of the kcalutils library.
+
+ Copyright (c) 1998 Preston Brown <pbrown@kde.org>
+ Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+ Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
+ Copyright (c) 2008 Thomas Thrainer <tom_t@gmx.at>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ @file
+ This file is part of the API for handling calendar data and
+ defines the DndFactory class.
+
+ @brief
+ vCalendar/iCalendar Drag-and-Drop object factory.
+
+ @author Preston Brown \<pbrown@kde.org\>
+ @author Cornelius Schumacher \<schumacher@kde.org\>
+ @author Reinhold Kainhofer \<reinhold@kainhofer.com\>
+*/
+#include "dndfactory.h"
+#include "icaldrag.h"
+#include "vcaldrag.h"
+
+#include <KDebug>
+#include <KIconLoader> // for BarIcon
+#include <KUrl>
+
+#include <QtCore/QMimeData>
+#include <QtGui/QApplication>
+#include <QtGui/QClipboard>
+#include <QtGui/QDrag>
+#include <QtGui/QDropEvent>
+#include <QtGui/QPixmap>
+
+using namespace KCalCore;
+using namespace KCalUtils;
+
+/**
+ Private class that helps to provide binary compatibility between releases.
+ @internal
+*/
+//@cond PRIVATE
+class KCalUtils::DndFactory::Private
+{
+ public:
+ Private( const MemoryCalendar::Ptr &calendar )
+ : mCalendar ( calendar )
+ {}
+
+ Incidence::Ptr pasteIncidence( const Incidence::Ptr &incidence,
+ const KDateTime &newDateTime,
+ const QFlags<PasteFlag> &pasteOptions )
+ {
+
+ Incidence::Ptr inc( incidence );
+
+ if ( inc ) {
+ inc = Incidence::Ptr( inc->clone() );
+ inc->recreate();
+ }
+
+ if ( inc && newDateTime.isValid() ) {
+ if ( inc->type() == Incidence::TypeEvent ) {
+
+ Event::Ptr event = inc.staticCast<Event>();
+
+ // in seconds
+ const int durationInSeconds = event->dtStart().secsTo( event->dtEnd() );
+ const int durationInDays = event->dtStart().daysTo( event->dtEnd() );
+
+ event->setDtStart( newDateTime );
+
+ if ( newDateTime.isDateOnly() ) {
+ event->setDtEnd( newDateTime.addDays( durationInDays ) );
+ } else {
+ event->setDtEnd( newDateTime.addSecs( durationInSeconds ) );
+ }
+
+ } else if ( inc->type() == Incidence::TypeTodo ) {
+ Todo::Ptr aTodo = inc.staticCast<Todo>();
+
+ if ( pasteOptions & FlagTodosPasteAtDtStart ) {
+ aTodo->setDtStart( newDateTime );
+ } else {
+ aTodo->setDtDue( newDateTime );
+ }
+
+ } else if ( inc->type() == Incidence::TypeJournal ) {
+ inc->setDtStart( newDateTime );
+ } else {
+ kDebug() << "Trying to paste unknown incidence of type" << int( inc->type() );
+ }
+ }
+
+ return inc;
+ }
+
+ MemoryCalendar::Ptr mCalendar;
+};
+//@endcond
+
+DndFactory::DndFactory( const MemoryCalendar::Ptr &calendar )
+ : d( new KCalUtils::DndFactory::Private ( calendar ) )
+{
+}
+
+DndFactory::~DndFactory()
+{
+ delete d;
+}
+
+QMimeData *DndFactory::createMimeData()
+{
+ QMimeData *mimeData = new QMimeData;
+
+ ICalDrag::populateMimeData( mimeData, d->mCalendar );
+ VCalDrag::populateMimeData( mimeData, d->mCalendar );
+
+ return mimeData;
+}
+
+QDrag *DndFactory::createDrag( QWidget *owner )
+{
+ QDrag *drag = new QDrag( owner );
+ drag->setMimeData( createMimeData() );
+
+ return drag;
+}
+
+QMimeData *DndFactory::createMimeData( const Incidence::Ptr &incidence )
+{
+ MemoryCalendar::Ptr cal( new MemoryCalendar( d->mCalendar->timeSpec() ) );
+ Incidence::Ptr i( incidence->clone() );
+ cal->addIncidence( i );
+
+ QMimeData *mimeData = new QMimeData;
+
+ ICalDrag::populateMimeData( mimeData, cal );
+ VCalDrag::populateMimeData( mimeData, cal );
+
+ KUrl uri = i->uri();
+ if ( uri.isValid() ) {
+ QMap<QString, QString> metadata;
+ metadata["labels"] = KUrl::toPercentEncoding( i->summary() );
+ uri.populateMimeData( mimeData, metadata );
+ }
+
+ return mimeData;
+}
+
+QDrag *DndFactory::createDrag( const Incidence::Ptr &incidence, QWidget *owner )
+{
+ QDrag *drag = new QDrag( owner );
+ drag->setMimeData( createMimeData( incidence ) );
+ drag->setPixmap( BarIcon( incidence->iconName() ) );
+
+ return drag;
+}
+
+MemoryCalendar::Ptr DndFactory::createDropCalendar( const QMimeData *mimeData )
+{
+ return createDropCalendar( mimeData, d->mCalendar->timeSpec() );
+}
+
+MemoryCalendar::Ptr DndFactory::createDropCalendar( const QMimeData *mimeData,
+ const KDateTime::Spec &timeSpec )
+{
+ MemoryCalendar::Ptr calendar( new MemoryCalendar( timeSpec ) );
+
+ if ( ICalDrag::fromMimeData( mimeData, calendar ) ||
+ VCalDrag::fromMimeData( mimeData, calendar ) ){
+ return calendar;
+ }
+
+ return MemoryCalendar::Ptr();
+}
+
+MemoryCalendar::Ptr DndFactory::createDropCalendar( QDropEvent *dropEvent )
+{
+ MemoryCalendar::Ptr calendar( createDropCalendar( dropEvent->mimeData() ) );
+ if ( calendar ) {
+ dropEvent->accept();
+ return calendar;
+ }
+ return MemoryCalendar::Ptr();
+}
+
+Event::Ptr DndFactory::createDropEvent( const QMimeData *mimeData )
+{
+ kDebug();
+ Event::Ptr event;
+ MemoryCalendar::Ptr calendar( createDropCalendar( mimeData ) );
+
+ if ( calendar ) {
+ Event::List events = calendar->events();
+ if ( !events.isEmpty() ) {
+ event = Event::Ptr( new Event( *events.first() ) );
+ }
+ }
+ return event;
+}
+
+Event::Ptr DndFactory::createDropEvent( QDropEvent *dropEvent )
+{
+ Event::Ptr event = createDropEvent( dropEvent->mimeData() );
+
+ if ( event ) {
+ dropEvent->accept();
+ }
+
+ return event;
+}
+
+Todo::Ptr DndFactory::createDropTodo( const QMimeData *mimeData )
+{
+ kDebug();
+ Todo::Ptr todo;
+ MemoryCalendar::Ptr calendar( createDropCalendar( mimeData ) );
+
+ if ( calendar ) {
+ Todo::List todos = calendar->todos();
+ if ( !todos.isEmpty() ) {
+ todo = Todo::Ptr( new Todo( *todos.first() ) );
+ }
+ }
+
+ return todo;
+}
+
+Todo::Ptr DndFactory::createDropTodo( QDropEvent *dropEvent )
+{
+ Todo::Ptr todo = createDropTodo( dropEvent->mimeData() );
+
+ if ( todo ) {
+ dropEvent->accept();
+ }
+
+ return todo;
+}
+
+void DndFactory::cutIncidence( const Incidence::Ptr &selectedIncidence )
+{
+ Incidence::List list;
+ list.append( selectedIncidence );
+ cutIncidences( list );
+}
+
+bool DndFactory::cutIncidences( const Incidence::List &incidences )
+{
+ if ( copyIncidences( incidences ) ) {
+ Incidence::List::ConstIterator it;
+ for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
+ d->mCalendar->deleteIncidence( *it );
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool DndFactory::copyIncidences( const Incidence::List &incidences )
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ Q_ASSERT( clipboard );
+ MemoryCalendar::Ptr calendar( new MemoryCalendar( d->mCalendar->timeSpec() ) );
+
+ Incidence::List::ConstIterator it;
+ for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
+ if ( *it ) {
+ calendar->addIncidence( Incidence::Ptr( ( *it )->clone() ) );
+ }
+ }
+
+ QMimeData *mimeData = new QMimeData;
+
+ ICalDrag::populateMimeData( mimeData, calendar );
+ VCalDrag::populateMimeData( mimeData, calendar );
+
+ if ( calendar->incidences().isEmpty() ) {
+ return false;
+ } else {
+ clipboard->setMimeData( mimeData );
+ return true;
+ }
+}
+
+bool DndFactory::copyIncidence( const Incidence::Ptr &selectedInc )
+{
+ Incidence::List list;
+ list.append( selectedInc );
+ return copyIncidences( list );
+}
+
+Incidence::List DndFactory::pasteIncidences( const KDateTime &newDateTime,
+ const QFlags<PasteFlag> &pasteOptions )
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ Q_ASSERT( clipboard );
+ MemoryCalendar::Ptr calendar( createDropCalendar( clipboard->mimeData() ) );
+ Incidence::List list;
+
+ if ( !calendar ) {
+ kDebug() << "Can't parse clipboard";
+ return list;
+ }
+
+ // All pasted incidences get new uids, must keep track of old uids,
+ // so we can update child's parents
+ QHash<QString, Incidence::Ptr> oldUidToNewInc;
+
+ Incidence::List::ConstIterator it;
+ const Incidence::List incidences = calendar->incidences();
+ for ( it = incidences.constBegin();
+ it != incidences.constEnd(); ++it ) {
+ Incidence::Ptr incidence = d->pasteIncidence( *it, newDateTime, pasteOptions );
+ if ( incidence ) {
+ list.append( incidence );
+ oldUidToNewInc[(*it)->uid()] = *it;
+ }
+ }
+
+ // update relations
+ for ( it = list.constBegin(); it != list.constEnd(); ++it ) {
+ Incidence::Ptr incidence = *it;
+ if ( oldUidToNewInc.contains( incidence->relatedTo() ) ) {
+ Incidence::Ptr parentInc = oldUidToNewInc[incidence->relatedTo()];
+ incidence->setRelatedTo( parentInc->uid() );
+ } else {
+ // not related to anything in the clipboard
+ incidence->setRelatedTo( QString() );
+ }
+ }
+
+ return list;
+}
+
+Incidence::Ptr DndFactory::pasteIncidence( const KDateTime &newDateTime,
+ const QFlags<PasteFlag> &pasteOptions )
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ MemoryCalendar::Ptr calendar( createDropCalendar( clipboard->mimeData() ) );
+
+ if ( !calendar ) {
+ kDebug() << "Can't parse clipboard";
+ return Incidence::Ptr();
+ }
+
+ Incidence::List incidenceList = calendar->incidences();
+ Incidence::Ptr incidence = incidenceList.isEmpty() ? Incidence::Ptr() : incidenceList.first();
+
+ return d->pasteIncidence( incidence, newDateTime, pasteOptions );
+}