20 #include "calendarclipboard_p.h"
21 #include <kcalutils/dndfactory.h>
22 #include <kcalutils/icaldrag.h>
25 #include <KMessageBox>
27 #include <QApplication>
30 using namespace Akonadi;
32 CalendarClipboard::Private::Private(
const Akonadi::CalendarBase::Ptr &calendar,
33 Akonadi::IncidenceChanger *changer,
34 CalendarClipboard *qq ) : QObject( qq )
35 , m_calendar( calendar )
36 , m_changer( changer )
37 , m_abortCurrentOperation( false )
40 Q_ASSERT( m_calendar );
42 m_changer =
new Akonadi::IncidenceChanger(
this );
43 m_changer->setHistoryEnabled(
false );
44 m_changer->setGroupwareCommunication(
false );
47 m_dndfactory =
new KCalUtils::DndFactory( m_calendar );
51 SLOT(slotModifyFinished(
int,
Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)) );
54 SIGNAL(
deleteFinished(
int,QVector<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)),
55 SLOT(slotDeleteFinished(
int,QVector<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)) );
58 CalendarClipboard::Private::~Private()
63 void CalendarClipboard::Private::getIncidenceHierarchy(
const KCalCore::Incidence::Ptr &incidence,
67 if ( incidence && !uids.contains( incidence->uid() ) ) {
68 KCalCore::Incidence::List immediateChildren = m_calendar->childIncidences( incidence->uid() );
70 foreach(
const KCalCore::Incidence::Ptr &child, immediateChildren ) {
71 getIncidenceHierarchy( child, uids );
73 uids.append( incidence->uid() );
77 void CalendarClipboard::Private::cut(
const KCalCore::Incidence::List &incidences )
79 const bool result = m_dndfactory->copyIncidences( incidences );
80 m_pendingChangeIds.clear();
85 const int result = m_changer->deleteIncidences( items );
87 emit q->cutFinished(
false, i18n(
"Error performing deletion." ) );
89 m_pendingChangeIds << result;
92 emit q->cutFinished(
false, i18n(
"Error performing copy." ) );
96 void CalendarClipboard::Private::cut(
const KCalCore::Incidence::Ptr &incidence )
98 KCalCore::Incidence::List incidences;
99 incidences << incidence;
103 void CalendarClipboard::Private::makeChildsIndependent(
const KCalCore::Incidence::Ptr &incidence )
105 Q_ASSERT( incidence );
106 const KCalCore::Incidence::List childs = m_calendar->childIncidences( incidence->uid() );
108 if ( childs.isEmpty() ) {
111 m_pendingChangeIds.clear();
112 m_abortCurrentOperation =
false;
113 foreach(
const KCalCore::Incidence::Ptr &child, childs ) {
114 Akonadi::Item childItem = m_calendar->item( incidence->uid() );
116 emit q->cutFinished(
false, i18n(
"Can't find item: %1", childItem.
id() ) );
120 KCalCore::Incidence::Ptr newIncidence( child->clone() );
121 newIncidence->setRelatedTo( QString() );
122 childItem.
setPayload<KCalCore::Incidence::Ptr>( newIncidence );
123 const int changeId = m_changer->modifyIncidence( childItem, child );
124 if ( changeId == -1 ) {
125 m_abortCurrentOperation =
true;
128 m_pendingChangeIds << changeId;
131 if ( m_pendingChangeIds.isEmpty() && m_abortCurrentOperation ) {
132 emit q->cutFinished(
false, i18n(
"Error while removing relations." ) );
137 void CalendarClipboard::Private::slotModifyFinished(
int changeId,
const Akonadi::Item &item,
138 IncidenceChanger::ResultCode resultCode,
139 const QString &errorMessage )
141 if ( !m_pendingChangeIds.contains( changeId ) )
144 m_pendingChangeIds.remove( changeId );
145 const bool isLastChange = m_pendingChangeIds.isEmpty();
148 Q_UNUSED( errorMessage );
149 if ( m_abortCurrentOperation && isLastChange ) {
150 emit q->cutFinished(
false, i18n(
"Error while removing relations." ) );
151 }
else if ( !m_abortCurrentOperation ) {
152 if ( resultCode == IncidenceChanger::ResultCodeSuccess ) {
153 if ( isLastChange ) {
156 cut( item.
payload<KCalCore::Incidence::Ptr>() );
159 m_abortCurrentOperation =
true;
164 void CalendarClipboard::Private::slotDeleteFinished(
int changeId,
const QVector<Akonadi::Item::Id> &ids,
165 Akonadi::IncidenceChanger::ResultCode result,
166 const QString &errorMessage )
168 if ( !m_pendingChangeIds.contains( changeId ) )
171 m_pendingChangeIds.remove( changeId );
174 if ( result == IncidenceChanger::ResultCodeSuccess ) {
175 emit q->cutFinished(
true, QString() );
177 emit q->cutFinished(
false, i18n(
"Error while deleting incidences: %1",
182 CalendarClipboard::CalendarClipboard(
const Akonadi::CalendarBase::Ptr &calendar,
183 Akonadi::IncidenceChanger *changer,
184 QObject *parent ) : QObject( parent )
185 , d( new Private( calendar, changer, this ) )
191 CalendarClipboard::~CalendarClipboard()
195 void CalendarClipboard::cutIncidence(
const KCalCore::Incidence::Ptr &incidence,
196 CalendarClipboard::Mode mode )
198 const bool hasChildren = !d->m_calendar->childIncidences( incidence->uid() ).isEmpty();
199 if ( mode == AskMode && hasChildren ) {
200 const int km = KMessageBox::questionYesNoCancel( 0,
201 i18n(
"The item \"%1\" has sub-to-dos. "
202 "Do you want to cut just this item and "
203 "make all its sub-to-dos independent, or "
204 "cut the to-do with all its sub-to-dos?",
205 incidence->summary() ),
206 i18n(
"KOrganizer Confirmation" ),
207 KGuiItem( i18n(
"Cut Only This" ) ),
208 KGuiItem( i18n(
"Cut All" ) ) );
210 if ( km == KMessageBox::Cancel ) {
211 emit cutFinished(
true, QString() );
214 mode = km == KMessageBox::Yes ? SingleMode : RecursiveMode;
215 }
else if ( mode == AskMode ) {
219 if ( mode == SingleMode ) {
220 d->makeChildsIndependent( incidence );
223 d->getIncidenceHierarchy( incidence, uids );
224 Q_ASSERT( !uids.isEmpty() );
225 KCalCore::Incidence::List incidencesToCut;
226 foreach(
const QString &uid, uids ) {
227 KCalCore::Incidence::Ptr child = d->m_calendar->incidence( uid );
229 incidencesToCut << child;
231 d->cut( incidencesToCut );
235 bool CalendarClipboard::copyIncidence(
const KCalCore::Incidence::Ptr &incidence,
236 CalendarClipboard::Mode mode )
238 const bool hasChildren = !d->m_calendar->childIncidences( incidence->uid() ).isEmpty();
239 if ( mode == AskMode && hasChildren ) {
240 const int km = KMessageBox::questionYesNoCancel( 0,
241 i18n(
"The item \"%1\" has sub-to-dos. "
242 "Do you want to copy just this item or "
243 "copy the to-do with all its sub-to-dos?",
244 incidence->summary() ),
245 i18n(
"KOrganizer Confirmation" ),
246 KGuiItem( i18n(
"Copy Only This" ) ),
247 KGuiItem( i18n(
"Copy All" ) ) );
248 if ( km == KMessageBox::Cancel ) {
251 mode = km == KMessageBox::Yes ? SingleMode : RecursiveMode;
252 }
else if ( mode == AskMode ) {
256 KCalCore::Incidence::List incidencesToCopy;
257 if ( mode == SingleMode ) {
258 incidencesToCopy << incidence;
261 d->getIncidenceHierarchy( incidence, uids );
262 Q_ASSERT( !uids.isEmpty() );
263 foreach(
const QString &uid, uids ) {
264 KCalCore::Incidence::Ptr child = d->m_calendar->incidence( uid );
266 incidencesToCopy << child;
270 return d->m_dndfactory->copyIncidences( incidencesToCopy );
273 bool CalendarClipboard::pasteAvailable()
const
275 return KCalUtils::ICalDrag::canDecode( QApplication::clipboard()->mimeData() );