doc update
[kdepim.git] / korganizer / eventarchiver.cpp
blobcb2833e52fb1bf8bdf140ae4c3e15dd292880ec8
1 /*
2 This file is part of KOrganizer.
3 Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
4 Copyright (c) 2004 David Faure <faure@kde.org>
5 Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 As a special exception, permission is given to link this program
22 with any edition of Qt, and distribute the resulting executable,
23 without including the source code for Qt in the source distribution.
26 #include "eventarchiver.h"
27 #include "koprefs.h"
28 #include "incidencechanger.h"
30 #include <kio/netaccess.h>
31 #include <kcal/icalformat.h>
32 #include <kcal/filestorage.h>
33 #include <kcal/calendar.h>
34 #include <kcal/calendarlocal.h>
36 #include <akonadi/kcal/calendar.h>
37 #include <akonadi/kcal/calendaradaptor.h>
38 #include <akonadi/kcal/utils.h>
40 #include <kdebug.h>
41 #include <kglobal.h>
42 #include <klocale.h>
43 #include <ktemporaryfile.h>
44 #include <kmessagebox.h>
46 using namespace Akonadi;
47 using namespace KOrg;
49 EventArchiver::EventArchiver( QObject *parent )
50 : QObject( parent )
54 EventArchiver::~EventArchiver()
58 void EventArchiver::runOnce( Akonadi::Calendar *calendar, KOrg::IncidenceChangerBase* changer, const QDate &limitDate, QWidget *widget )
60 run( calendar, changer, limitDate, widget, true, true );
63 void EventArchiver::runAuto( Akonadi::Calendar *calendar, KOrg::IncidenceChangerBase* changer, QWidget *widget, bool withGUI )
65 QDate limitDate( QDate::currentDate() );
66 int expiryTime = KOPrefs::instance()->mExpiryTime;
67 switch ( KOPrefs::instance()->mExpiryUnit ) {
68 case KOPrefs::UnitDays: // Days
69 limitDate = limitDate.addDays( -expiryTime );
70 break;
71 case KOPrefs::UnitWeeks: // Weeks
72 limitDate = limitDate.addDays( -expiryTime * 7 );
73 break;
74 case KOPrefs::UnitMonths: // Months
75 limitDate = limitDate.addMonths( -expiryTime );
76 break;
77 default:
78 return;
80 run( calendar, changer, limitDate, widget, withGUI, false );
83 void EventArchiver::run( Akonadi::Calendar *calendar, KOrg::IncidenceChangerBase* changer, const QDate &limitDate, QWidget *widget,
84 bool withGUI, bool errorIfNone )
86 // We need to use rawEvents, otherwise events hidden by filters will not be archived.
87 Item::List events;
88 Item::List todos;
89 Item::List journals;
91 if ( KOPrefs::instance()->mArchiveEvents ) {
92 events = calendar->rawEvents(
93 QDate( 1769, 12, 1 ),
94 // #29555, also advertised by the "limitDate not included" in the class docu
95 limitDate.addDays( -1 ),
96 KOPrefs::instance()->timeSpec(),
97 true );
99 if ( KOPrefs::instance()->mArchiveTodos ) {
100 Item::List t = calendar->rawTodos();
101 Item::List::ConstIterator it;
102 for ( it = t.constBegin(); it != t.constEnd(); ++it ) {
103 const Todo::Ptr todo = Akonadi::todo( *it );
104 Q_ASSERT( todo );
105 if ( todo->isCompleted() && todo->completed().date() < limitDate ) {
106 todos.append( *it );
111 const Item::List incidences = Akonadi::Calendar::mergeIncidenceList( events, todos, journals );
113 kDebug() << "archiving incidences before" << limitDate
114 << " ->" << incidences.count() <<" incidences found.";
115 if ( incidences.isEmpty() ) {
116 if ( withGUI && errorIfNone ) {
117 KMessageBox::information( widget,
118 i18n( "There are no items before %1",
119 KGlobal::locale()->formatDate( limitDate ) ),
120 "ArchiverNoIncidences" );
122 return;
125 switch ( KOPrefs::instance()->mArchiveAction ) {
126 case KOPrefs::actionDelete:
127 deleteIncidences( calendar, changer, limitDate, widget, incidences, withGUI );
128 break;
129 case KOPrefs::actionArchive:
130 archiveIncidences( calendar, changer, limitDate, widget, incidences, withGUI );
131 break;
135 void EventArchiver::deleteIncidences( Akonadi::Calendar *calendar, KOrg::IncidenceChangerBase* changer, const QDate &limitDate, QWidget *widget,
136 const Item::List &incidences, bool withGUI )
138 QStringList incidenceStrs;
139 Item::List::ConstIterator it;
140 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
141 incidenceStrs.append( Akonadi::incidence( *it )->summary() );
144 if ( withGUI ) {
145 int result = KMessageBox::warningContinueCancelList(
146 widget,
147 i18n( "Delete all items before %1 without saving?\n"
148 "The following items will be deleted:",
149 KGlobal::locale()->formatDate( limitDate ) ),
150 incidenceStrs,
151 i18n( "Delete Old Items" ), KStandardGuiItem::del() );
152 if ( result != KMessageBox::Continue ) {
153 return;
156 for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
157 changer->deleteIncidence( *it, widget );
159 emit eventsDeleted();
162 void EventArchiver::archiveIncidences( Akonadi::Calendar *calendar, KOrg::IncidenceChangerBase* changer, const QDate &limitDate, QWidget *widget,
163 const Item::List &incidences, bool withGUI )
165 Q_UNUSED( limitDate );
166 Q_UNUSED( withGUI );
168 Akonadi::CalendarAdaptor cal( calendar, widget );
169 FileStorage storage( &cal );
171 // Save current calendar to disk
172 KTemporaryFile tmpFile;
173 tmpFile.open();
174 storage.setFileName( tmpFile.fileName() );
175 if ( !storage.save() ) {
176 kDebug() << "Can't save calendar to temp file";
177 return;
180 // Duplicate current calendar by loading in new calendar object
181 CalendarLocal archiveCalendar( KOPrefs::instance()->timeSpec() );
183 FileStorage archiveStore( &archiveCalendar );
184 archiveStore.setFileName( tmpFile.fileName() );
185 ICalFormat *format = new ICalFormat();
186 archiveStore.setSaveFormat( format );
187 if ( !archiveStore.load() ) {
188 kDebug() << "Can't load calendar from temp file";
189 return;
192 // Strip active events from calendar so that only events to be archived
193 // remain. This is not really efficient, but there is no other easy way.
194 QStringList uids;
195 Incidence::List allIncidences = archiveCalendar.rawIncidences();
196 foreach(const Akonadi::Item &item, incidences) {
197 uids.append( Akonadi::incidence(item)->uid() );
199 foreach(Incidence *inc, allIncidences) {
200 if ( !uids.contains( inc->uid() ) ) {
201 archiveCalendar.deleteIncidence( inc );
205 // Get or create the archive file
206 KUrl archiveURL( KOPrefs::instance()->mArchiveFile );
207 QString archiveFile;
209 if ( KIO::NetAccess::exists( archiveURL, KIO::NetAccess::SourceSide, widget ) ) {
210 if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
211 kDebug() << "Can't download archive file";
212 return;
214 // Merge with events to be archived.
215 archiveStore.setFileName( archiveFile );
216 if ( !archiveStore.load() ) {
217 kDebug() << "Can't merge with archive file";
218 return;
220 } else {
221 archiveFile = tmpFile.fileName();
224 // Save archive calendar
225 if ( !archiveStore.save() ) {
226 QString errmess;
227 if ( format->exception() ) {
228 errmess = format->exception()->message();
229 } else {
230 errmess = i18nc( "save failure cause unknown", "Reason unknown" );
232 KMessageBox::error( widget, i18n( "Cannot write archive file %1. %2",
233 archiveStore.fileName(), errmess ) );
234 return;
237 // Upload if necessary
238 KUrl srcUrl;
239 srcUrl.setPath( archiveFile );
240 if ( srcUrl != archiveURL ) {
241 if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
242 KMessageBox::error( widget, i18n( "Cannot write archive. %1",
243 KIO::NetAccess::lastErrorString() ) );
244 return;
248 KIO::NetAccess::removeTempFile( archiveFile );
250 // Delete archived events from calendar
251 foreach(const Akonadi::Item &item, incidences) {
252 changer->deleteIncidence( item, widget );
254 emit eventsDeleted();
257 #include "eventarchiver.moc"