20 #include "calendarclipboard_p.h"
21 #include <kcalutils/dndfactory.h>
22 #include <kcalutils/icaldrag.h>
24 #include <KLocalizedString>
25 #include <KMessageBox>
27 #include <QApplication>
30 using namespace Akonadi;
32 CalendarClipboard::Private::Private(
const Akonadi::CalendarBase::Ptr &calendar,
33 Akonadi::IncidenceChanger *changer,
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 );
50 SIGNAL(
modifyFinished(
int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
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();
84 Akonadi::Item::List items = m_calendar->itemList( incidences );
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 );
115 if ( !childItem.isValid() ) {
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 ) {
155 Q_ASSERT( item.isValid() && item.hasPayload() );
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",
183 Akonadi::IncidenceChanger *changer,
184 QObject *parent ) : QObject( parent )
185 , d( new Private( calendar, changer, this ) )
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 ) {
215 }
else if ( mode ==
AskMode ) {
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 );
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 ) {
252 }
else if ( mode ==
AskMode ) {
256 KCalCore::Incidence::List incidencesToCopy;
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 );
275 return KCalUtils::ICalDrag::canDecode( QApplication::clipboard()->mimeData() );
The specified incidence's children are also cut/copied.
bool pasteAvailable() const
Returns if there's any ical mime data available for pasting.
void deleteFinished(bool success, const QString &errorMessage)
This signal is emitted when an incidence is deleted in akonadi through delete{Incidence,Event,Todo,Journal} or deleteAll{Events,Todos,Journals}.
void modifyFinished(bool success, const QString &errorMessage)
This signal is emitted when an incidence is modified in akonadi through modifyIncidence().
The user is asked if he wants children to be cut/copied too.
Only the specified incidence is cut/copied.
CalendarClipboard(const Akonadi::CalendarBase::Ptr &calendar, Akonadi::IncidenceChanger *changer=0, QObject *parent=0)
Constructs a new CalendarClipboard.
bool copyIncidence(const KCalCore::Incidence::Ptr &incidence, CalendarClipboard::Mode mode=RecursiveMode)
Copies the specified incidence into the clipboard.
~CalendarClipboard()
Destroys the CalendarClipboard instance.
void cutFinished(bool success, const QString &errorMessage)
Emitted after cutIncidences() finishes.
Class to copy or cut calendar incidences.
void cutIncidence(const KCalCore::Incidence::Ptr &incidence, CalendarClipboard::Mode mode=RecursiveMode)
Copies the specified incidence into the clipboard and then deletes it from akonadi.