30 #include <Akonadi/Calendar/IncidenceChanger>
32 #include <KCalCore/ICalFormat>
33 #include <KCalCore/FileStorage>
34 #include <KCalCore/MemoryCalendar>
36 #include <KCalUtils/Stringify>
41 #include <KMessageBox>
42 #include <KTemporaryFile>
43 #include <KIO/NetAccess>
45 using namespace KCalCore;
46 using namespace KCalUtils;
47 using namespace CalendarSupport;
49 class GroupwareScoppedDisabler {
51 GroupwareScoppedDisabler(Akonadi::IncidenceChanger *changer) : m_changer(changer)
53 m_wasEnabled = m_changer->groupwareCommunication();
54 m_changer->setGroupwareCommunication(
false);
57 ~GroupwareScoppedDisabler()
59 m_changer->setGroupwareCommunication(m_wasEnabled);
63 Akonadi::IncidenceChanger *m_changer;
67 EventArchiver::EventArchiver(
QObject *parent )
77 Akonadi::IncidenceChanger *changer,
78 const QDate &limitDate,
QWidget *widget )
80 run( calendar, changer, limitDate, widget,
true,
true );
84 Akonadi::IncidenceChanger *changer,
87 QDate limitDate( QDate::currentDate() );
91 limitDate = limitDate.addDays( -expiryTime );
94 limitDate = limitDate.addDays( -expiryTime * 7 );
97 limitDate = limitDate.addMonths( -expiryTime );
102 run( calendar, changer, limitDate, widget, withGUI,
false );
105 void EventArchiver::run(
const Akonadi::ETMCalendar::Ptr &calendar,
106 Akonadi::IncidenceChanger *changer,
107 const QDate &limitDate,
QWidget *widget,
108 bool withGUI,
bool errorIfNone )
110 GroupwareScoppedDisabler disabler(changer);
113 KCalCore::Event::List events;
114 KCalCore::Todo::List
todos;
115 KCalCore::Journal::List journals;
118 events = calendar->rawEvents(
119 QDate( 1769, 12, 1 ),
121 limitDate.addDays( -1 ),
126 KCalCore::Todo::List rawTodos = calendar->rawTodos();
128 foreach(
const KCalCore::Todo::Ptr &
todo, rawTodos ) {
130 if ( isSubTreeComplete( calendar, todo, limitDate ) ) {
131 todos.append( todo );
136 const KCalCore::Incidence::List
incidences = calendar->mergeIncidenceList( events, todos, journals );
138 kDebug() <<
"archiving incidences before" << limitDate
139 <<
" ->" << incidences.count() <<
" incidences found.";
140 if ( incidences.isEmpty() ) {
141 if ( withGUI && errorIfNone ) {
142 KMessageBox::information( widget,
143 i18n(
"There are no items before %1",
144 KGlobal::locale()->formatDate( limitDate ) ),
145 QLatin1String(
"ArchiverNoIncidences") );
152 deleteIncidences( changer, limitDate, widget, calendar->itemList( incidences ), withGUI );
155 archiveIncidences( calendar, changer, limitDate, widget, incidences, withGUI );
160 void EventArchiver::deleteIncidences( Akonadi::IncidenceChanger *changer,
161 const QDate &limitDate,
QWidget *widget,
162 const Akonadi::Item::List &items,
bool withGUI )
164 QStringList incidenceStrs;
165 Akonadi::Item::List::ConstIterator it;
166 Akonadi::Item::List::ConstIterator end( items.constEnd() );
167 for ( it = items.constBegin(); it != end; ++it ) {
172 const int result = KMessageBox::warningContinueCancelList(
174 i18n(
"Delete all items before %1 without saving?\n"
175 "The following items will be deleted:",
176 KGlobal::locale()->formatDate( limitDate ) ),
178 i18n(
"Delete Old Items" ), KStandardGuiItem::del() );
179 if ( result != KMessageBox::Continue ) {
184 changer->deleteIncidences( items, widget );
190 void EventArchiver::archiveIncidences(
const Akonadi::ETMCalendar::Ptr &calendar,
191 Akonadi::IncidenceChanger *changer,
192 const QDate &limitDate,
QWidget *widget,
193 const KCalCore::Incidence::List &incidences,
bool withGUI )
195 Q_UNUSED( limitDate );
198 FileStorage storage( calendar );
206 KTemporaryFile tmpFile;
208 tmpFileName = tmpFile.fileName();
211 storage.setFileName( tmpFileName );
212 if ( !storage.save() ) {
213 kDebug() <<
"Can't save calendar to temp file";
218 MemoryCalendar::Ptr archiveCalendar(
221 FileStorage archiveStore( archiveCalendar );
222 archiveStore.setFileName( tmpFileName );
223 ICalFormat *format =
new ICalFormat();
224 archiveStore.setSaveFormat( format );
225 if ( !archiveStore.load() ) {
226 kDebug() <<
"Can't load calendar from temp file";
227 QFile::remove( tmpFileName );
234 Incidence::List allIncidences = archiveCalendar->rawIncidences();
235 foreach (
const KCalCore::Incidence::Ptr &
incidence, incidences ) {
236 uids.append( incidence->uid() );
238 foreach (
const KCalCore::Incidence::Ptr &incidence, allIncidences ) {
239 if ( !uids.contains( incidence->uid() ) ) {
240 archiveCalendar->deleteIncidence( incidence );
250 if ( KIO::NetAccess::exists( archiveURL, KIO::NetAccess::SourceSide, widget ) ) {
251 if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
252 kDebug() <<
"Can't download archive file";
253 QFile::remove( tmpFileName );
257 archiveStore.setFileName( archiveFile );
258 if ( !archiveStore.load() ) {
259 kDebug() <<
"Can't merge with archive file";
260 QFile::remove( tmpFileName );
264 archiveFile = tmpFileName;
267 archiveFile = archiveURL.toLocalFile();
268 archiveStore.setFileName( archiveFile );
272 if ( !archiveStore.save() ) {
274 if ( format->exception() ) {
275 errmess = Stringify::errorMessage( *format->exception() );
277 errmess = i18nc(
"save failure cause unknown",
"Reason unknown" );
279 KMessageBox::error( widget, i18n(
"Cannot write archive file %1. %2",
280 archiveStore.fileName(), errmess ) );
281 QFile::remove( tmpFileName );
288 srcUrl.setPath( archiveFile );
289 if ( srcUrl != archiveURL ) {
290 if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
291 KMessageBox::error( widget, i18n(
"Cannot write archive. %1",
292 KIO::NetAccess::lastErrorString() ) );
293 QFile::remove( tmpFileName );
298 KIO::NetAccess::removeTempFile( archiveFile );
300 QFile::remove( tmpFileName );
303 changer->startAtomicOperation( i18n(
"Archiving events" ) );
306 Akonadi::Item::List items = calendar->itemList( incidences );
307 foreach (
const Akonadi::Item &item, items ) {
308 changer->deleteIncidence( item, widget );
310 changer->endAtomicOperation();
315 bool EventArchiver::isSubTreeComplete(
const Akonadi::ETMCalendar::Ptr &calendar,
316 const Todo::Ptr &todo,
317 const QDate &limitDate,
318 QStringList checkedUids )
const
320 if ( !todo->isCompleted() || todo->completed().date() >= limitDate ) {
325 if ( checkedUids.contains( todo->uid() ) ) {
327 kWarning() <<
"To-do hierarchy loop detected!";
331 checkedUids.append( todo->uid() );
332 KCalCore::Incidence::List childs = calendar->childIncidences( todo->uid() );
333 foreach (
const KCalCore::Incidence::Ptr &incidence, childs ) {
334 const Todo::Ptr t = incidence.dynamicCast<KCalCore::Todo>();
335 if ( t && !isSubTreeComplete( calendar, t, limitDate, checkedUids ) ) {
343 #include "eventarchiver.moc"
void runAuto(const Akonadi::ETMCalendar::Ptr &calendar, Akonadi::IncidenceChanger *changer, QWidget *widget, bool withGUI)
Delete or archive events.
CALENDARSUPPORT_EXPORT KCalCore::Incidence::Ptr incidence(const Akonadi::Item &item)
returns the incidence from an akonadi item, or a null pointer if the item has no such payload ...
CALENDARSUPPORT_EXPORT KCalCore::Todo::Ptr todo(const Akonadi::Item &item)
returns the todo from an akonadi item, or a null pointer if the item has no such payload ...
CALENDARSUPPORT_EXPORT KCalCore::Incidence::List incidences(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
static KCalPrefs * instance()
Get instance of KCalPrefs.
void runOnce(const Akonadi::ETMCalendar::Ptr &calendar, Akonadi::IncidenceChanger *changer, const QDate &limitDate, QWidget *widget)
Delete or archive events once.
CALENDARSUPPORT_EXPORT KCalCore::Todo::List todos(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
KDateTime::Spec timeSpec()