korganizer

eventarchiver.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
00004     Copyright (c) 2004 David Faure <faure@kde.org>
00005     Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
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 <kmessagebox.h>
00036 #include <kdebug.h>
00037 #include "koprefs.h"
00038 
00039 EventArchiver::EventArchiver( QObject* parent, const char* name )
00040  : QObject( parent, name )
00041 {
00042 }
00043 
00044 EventArchiver::~EventArchiver()
00045 {
00046 }
00047 
00048 void EventArchiver::runOnce( Calendar* calendar, const QDate& limitDate, QWidget* widget )
00049 {
00050   run( calendar, limitDate, widget, true, true );
00051 }
00052 
00053 void EventArchiver::runAuto( Calendar* calendar, QWidget* widget, bool withGUI )
00054 {
00055   QDate limitDate( QDate::currentDate() );
00056   int expiryTime = KOPrefs::instance()->mExpiryTime;
00057   switch (KOPrefs::instance()->mExpiryUnit) {
00058   case KOPrefs::UnitDays: // Days
00059     limitDate = limitDate.addDays( -expiryTime );
00060     break;
00061   case KOPrefs::UnitWeeks: // Weeks
00062     limitDate = limitDate.addDays( -expiryTime*7 );
00063     break;
00064   case KOPrefs::UnitMonths: // Months
00065     limitDate = limitDate.addMonths( -expiryTime );
00066     break;
00067   default:
00068     return;
00069   }
00070   run( calendar, limitDate, widget, withGUI, false );
00071 }
00072 
00073 void EventArchiver::run( Calendar* calendar, const QDate& limitDate, QWidget* widget, bool withGUI,
00074                          bool errorIfNone )
00075 {
00076   // We need to use rawEvents, otherwise events hidden by filters will not be archived.
00077   Incidence::List incidences;
00078   Event::List events;
00079   Todo::List todos;
00080   Journal::List journals;
00081 
00082   if ( KOPrefs::instance()->mArchiveEvents ) {
00083     events = calendar->rawEvents(
00084       QDate( 1769, 12, 1 ),
00085       // #29555, also advertised by the "limitDate not included" in the class docu
00086       limitDate.addDays( -1 ),
00087       true );
00088   }
00089   if ( KOPrefs::instance()->mArchiveTodos ) {
00090     Todo::List t = calendar->rawTodos();
00091     Todo::List::ConstIterator it;
00092     for( it = t.begin(); it != t.end(); ++it ) {
00093       const bool todoComplete = (*it) &&
00094                                 (*it)->isCompleted() &&
00095                                 ( (*it)->completed().date() < limitDate );
00096 
00097       if ( todoComplete && !isSubTreeComplete( *it, limitDate ) ) {
00098         // The to-do is complete but some sub-todos are not.
00099         KMessageBox::information(
00100           widget,
00101           i18n( "Unable to archive to-do \"%1\" because at least one of its "
00102                 "sub-to-dos does not meet the archival requirements." ).arg( (*it)->summary() ),
00103           i18n( "Archive To-do" ),
00104           "UncompletedChildrenArchiveTodos" );
00105       } else if ( todoComplete ) {
00106         todos.append( *it );
00107       }
00108     }
00109   }
00110 
00111   incidences = Calendar::mergeIncidenceList( events, todos, journals );
00112 
00113 
00114   kdDebug(5850) << "EventArchiver: archiving incidences before " << limitDate << " -> "
00115                 << incidences.count() << " incidences found." << endl;
00116   if ( incidences.isEmpty() ) {
00117     if ( withGUI && errorIfNone ) {
00118       KMessageBox::information(
00119         widget,
00120         i18n( "There are no incidences available to archive before the specified cut-off date %1. "
00121               "Archiving will not be performed." ).arg( KGlobal::locale()->formatDate( limitDate ) ),
00122         "ArchiverNoIncidences" );
00123     }
00124     return;
00125   }
00126 
00127 
00128   switch ( KOPrefs::instance()->mArchiveAction ) {
00129   case KOPrefs::actionDelete:
00130     deleteIncidences( calendar, limitDate, widget, incidences, withGUI );
00131     break;
00132   case KOPrefs::actionArchive:
00133     archiveIncidences( calendar, limitDate, widget, incidences, withGUI );
00134     break;
00135   }
00136 }
00137 
00138 void EventArchiver::deleteIncidences( Calendar* calendar, const QDate& limitDate, QWidget* widget, const Incidence::List& incidences, bool withGUI )
00139 {
00140   QStringList incidenceStrs;
00141   Incidence::List::ConstIterator it;
00142   for( it = incidences.begin(); it != incidences.end(); ++it ) {
00143     incidenceStrs.append( (*it)->summary() );
00144   }
00145 
00146   if ( withGUI ) {
00147     int result = KMessageBox::warningContinueCancelList(
00148       widget, i18n("Delete all items before %1 without saving?\n"
00149                  "The following items will be deleted:")
00150       .arg(KGlobal::locale()->formatDate(limitDate)), incidenceStrs,
00151          i18n("Delete Old Items"),KStdGuiItem::del());
00152     if (result != KMessageBox::Continue)
00153       return;
00154   }
00155   for( it = incidences.begin(); it != incidences.end(); ++it ) {
00156     calendar->deleteIncidence( *it );
00157   }
00158   emit eventsDeleted();
00159 }
00160 
00161 void EventArchiver::archiveIncidences( Calendar* calendar, const QDate& /*limitDate*/, QWidget* widget, const Incidence::List& incidences, bool /*withGUI*/)
00162 {
00163   FileStorage storage( calendar );
00164 
00165   // Save current calendar to disk
00166   KTempFile tmpFile;
00167   tmpFile.setAutoDelete(true);
00168   storage.setFileName( tmpFile.name() );
00169   if ( !storage.save() ) {
00170     kdDebug(5850) << "EventArchiver::archiveEvents(): Can't save calendar to temp file" << endl;
00171     return;
00172   }
00173 
00174   // Duplicate current calendar by loading in new calendar object
00175   CalendarLocal archiveCalendar( KOPrefs::instance()->mTimeZoneId );
00176 
00177   FileStorage archiveStore( &archiveCalendar );
00178   archiveStore.setFileName( tmpFile.name() );
00179   if (!archiveStore.load()) {
00180     kdDebug(5850) << "EventArchiver::archiveEvents(): Can't load calendar from temp file" << endl;
00181     return;
00182   }
00183 
00184   // Strip active events from calendar so that only events to be archived
00185   // remain. This is not really efficient, but there is no other easy way.
00186   QStringList uids;
00187   Incidence::List allIncidences = archiveCalendar.rawIncidences();
00188   Incidence::List::ConstIterator it;
00189   for( it = incidences.begin(); it != incidences.end(); ++it ) {
00190     uids << (*it)->uid();
00191   }
00192   for( it = allIncidences.begin(); it != allIncidences.end(); ++it ) {
00193     if ( !uids.contains( (*it)->uid() ) ) {
00194       archiveCalendar.deleteIncidence( *it );
00195     }
00196   }
00197 
00198   // Get or create the archive file
00199   KURL archiveURL( KOPrefs::instance()->mArchiveFile );
00200   QString archiveFile;
00201 
00202   if ( KIO::NetAccess::exists( archiveURL, true, widget ) ) {
00203     if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
00204       kdDebug(5850) << "EventArchiver::archiveEvents(): Can't download archive file" << endl;
00205       return;
00206     }
00207     // Merge with events to be archived.
00208     archiveStore.setFileName( archiveFile );
00209     if ( !archiveStore.load() ) {
00210       kdDebug(5850) << "EventArchiver::archiveEvents(): Can't merge with archive file" << endl;
00211       return;
00212     }
00213   } else {
00214     archiveFile = tmpFile.name();
00215   }
00216 
00217   // Save archive calendar
00218   if ( !archiveStore.save() ) {
00219     KMessageBox::error(widget,i18n("Cannot write archive file %1.").arg( archiveStore.fileName() ));
00220     return;
00221   }
00222 
00223   // Upload if necessary
00224   KURL srcUrl;
00225   srcUrl.setPath(archiveFile);
00226   if (srcUrl != archiveURL) {
00227     if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
00228       KMessageBox::error(widget,i18n("Cannot write archive to final destination."));
00229       return;
00230     }
00231   }
00232 
00233   KIO::NetAccess::removeTempFile(archiveFile);
00234 
00235   // Delete archived events from calendar
00236   for( it = incidences.begin(); it != incidences.end(); ++it ) {
00237     calendar->deleteIncidence( *it );
00238   }
00239   emit eventsDeleted();
00240 }
00241 
00242 bool EventArchiver::isSubTreeComplete( const Todo *todo, const QDate &limitDate,
00243                                        QStringList checkedUids ) const
00244 {
00245   if ( !todo || !todo->isCompleted() || todo->completed().date() >= limitDate ) {
00246     return false;
00247   }
00248 
00249   // This QList is only to prevent infinit recursion
00250   if ( checkedUids.contains( todo->uid() ) ) {
00251     // Probably will never happen, calendar.cpp checks for this
00252     kdWarning() << "To-do hierarchy loop detected!";
00253     return false;
00254   }
00255 
00256   checkedUids.append( todo->uid() );
00257 
00258   Incidence::List::ConstIterator it;
00259   const Incidence::List relations = todo->relations();
00260 
00261   for( it = relations.begin(); it != relations.end(); ++it ) {
00262     if ( (*it)->type() == "Todo" ) {
00263       const Todo *t = static_cast<const Todo*>( *it );
00264       if ( !isSubTreeComplete( t, limitDate, checkedUids ) ) {
00265         return false;
00266       }
00267     }
00268   }
00269 
00270   return true;
00271 }
00272 
00273 #include "eventarchiver.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys