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
00166 QValueList<Incidence*> deletedIncidences;
00167 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00168 if ( !deletedIncidences.contains( *it ) ) {
00169 calendar->deleteIncidence( *it );
00170 deletedIncidences << *it;
00171 } else {
00172 kdWarning(5850) << "EventArchiver::deleteIncidences(): Tried to delete the same incidence twice!" << endl;
00173 }
00174 }
00175 emit eventsDeleted();
00176 }
00177
00178 void EventArchiver::archiveIncidences( Calendar* calendar, const QDate& , QWidget* widget, const Incidence::List& incidences, bool )
00179 {
00180 FileStorage storage( calendar );
00181
00182
00183 KTempFile tmpFile;
00184 tmpFile.setAutoDelete(true);
00185 storage.setFileName( tmpFile.name() );
00186 if ( !storage.save() ) {
00187 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't save calendar to temp file" << endl;
00188 return;
00189 }
00190
00191
00192 CalendarLocal archiveCalendar( KOPrefs::instance()->mTimeZoneId );
00193
00194 FileStorage archiveStore( &archiveCalendar );
00195 archiveStore.setFileName( tmpFile.name() );
00196 if (!archiveStore.load()) {
00197 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't load calendar from temp file" << endl;
00198 return;
00199 }
00200
00201
00202
00203 QStringList uids;
00204 Incidence::List allIncidences = archiveCalendar.rawIncidences();
00205 Incidence::List::ConstIterator it;
00206 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00207 uids << (*it)->uid();
00208 }
00209 for( it = allIncidences.begin(); it != allIncidences.end(); ++it ) {
00210 if ( !uids.contains( (*it)->uid() ) ) {
00211 archiveCalendar.deleteIncidence( *it );
00212 }
00213 }
00214
00215
00216 KURL archiveURL( KOPrefs::instance()->mArchiveFile );
00217 QString archiveFile;
00218
00219 if ( KIO::NetAccess::exists( archiveURL, true, widget ) ) {
00220 if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
00221 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't download archive file" << endl;
00222 return;
00223 }
00224
00225 archiveStore.setFileName( archiveFile );
00226 if ( !archiveStore.load() ) {
00227 kdDebug(5850) << "EventArchiver::archiveEvents(): Can't merge with archive file" << endl;
00228 return;
00229 }
00230 } else {
00231 archiveFile = tmpFile.name();
00232 }
00233
00234
00235 if ( !archiveStore.save() ) {
00236 KMessageBox::error(widget,i18n("Cannot write archive file %1.").arg( archiveStore.fileName() ));
00237 return;
00238 }
00239
00240
00241 KURL srcUrl;
00242 srcUrl.setPath(archiveFile);
00243 if (srcUrl != archiveURL) {
00244 if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
00245 KMessageBox::error(widget,i18n("Cannot write archive to final destination."));
00246 return;
00247 }
00248 }
00249
00250 KIO::NetAccess::removeTempFile(archiveFile);
00251
00252
00253 QValueList<Incidence*> deletedIncidences;
00254 for( it = incidences.begin(); it != incidences.end(); ++it ) {
00255 if ( !deletedIncidences.contains( *it ) ) {
00256 calendar->deleteIncidence( *it );
00257 deletedIncidences << *it;
00258 } else {
00259 kdWarning(5850) << "EventArchiver::archiveEvents(): Tried to delete the same incidence twice!" << endl;
00260 }
00261 }
00262 emit eventsDeleted();
00263 }
00264
00265 bool EventArchiver::isSubTreeComplete( const Todo *todo, const QDate &limitDate,
00266 QStringList checkedUids ) const
00267 {
00268 if ( !todo || !todo->isCompleted() || todo->completed().date() >= limitDate ) {
00269 return false;
00270 }
00271
00272
00273 if ( checkedUids.contains( todo->uid() ) ) {
00274
00275 kdWarning() << "To-do hierarchy loop detected!";
00276 return false;
00277 }
00278
00279 checkedUids.append( todo->uid() );
00280
00281 Incidence::List::ConstIterator it;
00282 const Incidence::List relations = todo->relations();
00283
00284 for( it = relations.begin(); it != relations.end(); ++it ) {
00285 if ( (*it)->type() == "Todo" ) {
00286 const Todo *t = static_cast<const Todo*>( *it );
00287 if ( !isSubTreeComplete( t, limitDate, checkedUids ) ) {
00288 return false;
00289 }
00290 }
00291 }
00292
00293 return true;
00294 }
00295
00296 #include "eventarchiver.moc"