00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "eventarchiver.h"
00027 #include <kglobal.h>
00028 #include <klocale.h>
00029 #include <ktempfile.h>
00030 #include <kio/netaccess.h>
00031 #include <kglobal.h>
00032 #include <libkcal/filestorage.h>
00033 #include <libkcal/calendarlocal.h>
00034 #include <libkcal/calendar.h>
00035 #include <libkcal/calhelper.h>
00036 #include <kmessagebox.h>
00037 #include <kdebug.h>
00038 #include "koprefs.h"
00039
00040 EventArchiver::EventArchiver( QObject* parent, const char* name )
00041 : QObject( parent, name )
00042 {
00043 }
00044
00045 EventArchiver::~EventArchiver()
00046 {
00047 }
00048
00049 void EventArchiver::runOnce( Calendar* calendar, const QDate& limitDate, QWidget* widget )
00050 {
00051 run( calendar, limitDate, widget, true, true );
00052 }
00053
00054 void EventArchiver::runAuto( Calendar* calendar, QWidget* widget, bool withGUI )
00055 {
00056 QDate limitDate( QDate::currentDate() );
00057 int expiryTime = KOPrefs::instance()->mExpiryTime;
00058 switch (KOPrefs::instance()->mExpiryUnit) {
00059 case KOPrefs::UnitDays:
00060 limitDate = limitDate.addDays( -expiryTime );
00061 break;
00062 case KOPrefs::UnitWeeks:
00063 limitDate = limitDate.addDays( -expiryTime*7 );
00064 break;
00065 case KOPrefs::UnitMonths:
00066 limitDate = limitDate.addMonths( -expiryTime );
00067 break;
00068 default:
00069 return;
00070 }
00071 run( calendar, limitDate, widget, withGUI, false );
00072 }
00073
00074 void EventArchiver::run( Calendar* calendar, const QDate& limitDate, QWidget* widget, bool withGUI,
00075 bool errorIfNone )
00076 {
00077
00078 Incidence::List incidences;
00079 Event::List events;
00080 Todo::List todos;
00081 Journal::List journals;
00082
00083 if ( KOPrefs::instance()->mArchiveEvents ) {
00084 events = calendar->rawEvents(
00085 QDate( 1769, 12, 1 ),
00086
00087 limitDate.addDays( -1 ),
00088 true );
00089 }
00090 if ( KOPrefs::instance()->mArchiveTodos ) {
00091 Todo::List t = calendar->rawTodos();
00092 Todo::List::ConstIterator it;
00093 for( it = t.begin(); it != t.end(); ++it ) {
00094 const bool todoComplete = (*it) &&
00095 (*it)->isCompleted() &&
00096 ( (*it)->completed().date() < limitDate );
00097
00098 if ( todoComplete && !isSubTreeComplete( *it, limitDate ) ) {
00099
00100 KMessageBox::information(
00101 widget,
00102 i18n( "Unable to archive to-do \"%1\" because at least one of its "
00103 "sub-to-dos does not meet the archival requirements." ).arg( (*it)->summary() ),
00104 i18n( "Archive To-do" ),
00105 "UncompletedChildrenArchiveTodos" );
00106 } else if ( todoComplete ) {
00107 todos.append( *it );
00108 }
00109 }
00110 }
00111
00112 const Incidence::List allIncidences = Calendar::mergeIncidenceList( events, todos, journals );
00113
00114 if (KOPrefs::instance()->mArchiveOwnFoldersOnly) {
00115 for (int i = 0; i < allIncidences.count(); ++i) {
00116 Incidence *incidence = allIncidences[i];
00117 if (CalHelper::isMyCalendarIncidence( calendar, incidence ) )
00118 incidences.append( incidence );
00119 }
00120 } else {
00121 incidences = allIncidences;
00122 }
00123
00124 kdDebug(5850) << "EventArchiver: archiving incidences before " << limitDate << " -> "
00125 << incidences.count() << " incidences found." << endl;
00126 if ( incidences.isEmpty() ) {
00127 if ( withGUI && errorIfNone ) {
00128 KMessageBox::information(
00129 widget,
00130 i18n( "There are no incidences available to archive before the specified cut-off date %1. "
00131 "Archiving will not be performed." ).arg( KGlobal::locale()->formatDate( limitDate ) ),
00132 "ArchiverNoIncidences" );
00133 }
00134 return;
00135 }
00136
00137
00138 switch ( KOPrefs::instance()->mArchiveAction ) {
00139 case KOPrefs::actionDelete:
00140 deleteIncidences( calendar, limitDate, widget, incidences, withGUI );
00141 break;
00142 case KOPrefs::actionArchive:
00143 archiveIncidences( calendar, limitDate, widget, incidences, withGUI );
00144 break;
00145 }
00146 }
00147
00148 void EventArchiver::deleteIncidences( Calendar* calendar, const QDate& limitDate, QWidget* widget, const Incidence::List& incidences, bool withGUI )
00149 {
00150 QStringList incidenceStrs;
00151 Incidence::List::ConstIterator it;
00152 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00153 incidenceStrs.append( (*it)->summary() );
00154 }
00155
00156 if ( withGUI ) {
00157 int result = KMessageBox::warningContinueCancelList(
00158 widget, i18n("Delete all items before %1 without saving?\n"
00159 "The following items will be deleted:")
00160 .arg(KGlobal::locale()->formatDate(limitDate)), incidenceStrs,
00161 i18n("Delete Old Items"),KStdGuiItem::del());
00162 if (result != KMessageBox::Continue)
00163 return;
00164 }
00165 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00166 calendar->deleteIncidence( *it );
00167 }
00168 emit eventsDeleted();
00169 }
00170
00171 void EventArchiver::archiveIncidences( Calendar* calendar, const QDate& , QWidget* widget, const Incidence::List& incidences, bool )
00172 {
00173 FileStorage storage( calendar );
00174
00175
00176 KTempFile tmpFile;
00177 tmpFile.setAutoDelete(true);
00178 storage.setFileName( tmpFile.name() );
00179 if ( !storage.save() ) {
00180 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't save calendar to temp file" << endl;
00181 return;
00182 }
00183
00184
00185 CalendarLocal archiveCalendar( KOPrefs::instance()->mTimeZoneId );
00186
00187 FileStorage archiveStore( &archiveCalendar );
00188 archiveStore.setFileName( tmpFile.name() );
00189 if (!archiveStore.load()) {
00190 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't load calendar from temp file" << endl;
00191 return;
00192 }
00193
00194
00195
00196 QStringList uids;
00197 Incidence::List allIncidences = archiveCalendar.rawIncidences();
00198 Incidence::List::ConstIterator it;
00199 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00200 uids << (*it)->uid();
00201 }
00202 for( it = allIncidences.begin(); it != allIncidences.end(); ++it ) {
00203 if ( !uids.contains( (*it)->uid() ) ) {
00204 archiveCalendar.deleteIncidence( *it );
00205 }
00206 }
00207
00208
00209 KURL archiveURL( KOPrefs::instance()->mArchiveFile );
00210 QString archiveFile;
00211
00212 if ( KIO::NetAccess::exists( archiveURL, true, widget ) ) {
00213 if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
00214 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't download archive file" << endl;
00215 return;
00216 }
00217
00218 archiveStore.setFileName( archiveFile );
00219 if ( !archiveStore.load() ) {
00220 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't merge with archive file" << endl;
00221 return;
00222 }
00223 } else {
00224 archiveFile = tmpFile.name();
00225 }
00226
00227
00228 if ( !archiveStore.save() ) {
00229 KMessageBox::error(widget,i18n("Cannot write archive file %1.").arg( archiveStore.fileName() ));
00230 return;
00231 }
00232
00233
00234 KURL srcUrl;
00235 srcUrl.setPath(archiveFile);
00236 if (srcUrl != archiveURL) {
00237 if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
00238 KMessageBox::error(widget,i18n("Cannot write archive to final destination."));
00239 return;
00240 }
00241 }
00242
00243 KIO::NetAccess::removeTempFile(archiveFile);
00244
00245
00246 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00247 calendar->deleteIncidence( *it );
00248 }
00249 emit eventsDeleted();
00250 }
00251
00252 bool EventArchiver::isSubTreeComplete( const Todo *todo, const QDate &limitDate,
00253 QStringList checkedUids ) const
00254 {
00255 if ( !todo || !todo->isCompleted() || todo->completed().date() >= limitDate ) {
00256 return false;
00257 }
00258
00259
00260 if ( checkedUids.contains( todo->uid() ) ) {
00261
00262 kdWarning() << "To-do hierarchy loop detected!";
00263 return false;
00264 }
00265
00266 checkedUids.append( todo->uid() );
00267
00268 Incidence::List::ConstIterator it;
00269 const Incidence::List relations = todo->relations();
00270
00271 for( it = relations.begin(); it != relations.end(); ++it ) {
00272 if ( (*it)->type() == "Todo" ) {
00273 const Todo *t = static_cast<const Todo*>( *it );
00274 if ( !isSubTreeComplete( t, limitDate, checkedUids ) ) {
00275 return false;
00276 }
00277 }
00278 }
00279
00280 return true;
00281 }
00282
00283 #include "eventarchiver.moc"