30 #include <Akonadi/Calendar/IncidenceChanger> 
   32 #include <KCalCore/ICalFormat> 
   33 #include <KCalCore/FileStorage> 
   34 #include <KCalCore/MemoryCalendar> 
   36 #include <KCalUtils/Stringify> 
   40 #include <KLocalizedString> 
   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,
 
   80   run( calendar, changer, limitDate, widget, 
true, 
true );
 
   84                              Akonadi::IncidenceChanger *changer,
 
   90   case KCalPrefs::UnitDays: 
 
   91     limitDate = limitDate.
addDays( -expiryTime );
 
   93   case KCalPrefs::UnitWeeks: 
 
   94     limitDate = limitDate.
addDays( -expiryTime * 7 );
 
   96   case KCalPrefs::UnitMonths: 
 
   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,
 
  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 ),
 
  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 ) ),
 
  151   case KCalPrefs::actionDelete:
 
  152     deleteIncidences( changer, limitDate, widget, calendar->itemList( incidences ), withGUI );
 
  154   case KCalPrefs::actionArchive:
 
  155     archiveIncidences( calendar, changer, limitDate, widget, incidences, withGUI );
 
  160 void EventArchiver::deleteIncidences( Akonadi::IncidenceChanger *changer,
 
  162                                       const Akonadi::Item::List &items, 
bool withGUI )
 
  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,
 
  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";
 
  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 );
 
  249   if ( KIO::NetAccess::exists( archiveURL, KIO::NetAccess::SourceSide, widget ) ) {
 
  250     if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
 
  251       kDebug() << 
"Can't download archive file";
 
  256     archiveStore.setFileName( archiveFile );
 
  257     if ( !archiveStore.load() ) {
 
  258       kDebug() << 
"Can't merge with archive file";
 
  263     archiveFile = tmpFileName;
 
  267   if ( !archiveStore.save() ) {
 
  269     if ( format->exception() ) {
 
  270       errmess = Stringify::errorMessage( *format->exception() );
 
  272       errmess = i18nc( 
"save failure cause unknown", 
"Reason unknown" );
 
  274     KMessageBox::error( widget, i18n( 
"Cannot write archive file %1. %2",
 
  275                                       archiveStore.fileName(), errmess ) );
 
  282   srcUrl.setPath( archiveFile );
 
  283   if ( srcUrl != archiveURL ) {
 
  284     if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
 
  285       KMessageBox::error( widget, i18n( 
"Cannot write archive. %1",
 
  286                                         KIO::NetAccess::lastErrorString() ) );
 
  292   KIO::NetAccess::removeTempFile( archiveFile );
 
  296   changer->startAtomicOperation( i18n( 
"Archiving events" ) );
 
  299   Akonadi::Item::List items = calendar->itemList( incidences );
 
  300   foreach ( 
const Akonadi::Item &item, items ) {
 
  301     changer->deleteIncidence( item, widget );
 
  303   changer->endAtomicOperation();
 
  308 bool EventArchiver::isSubTreeComplete( 
const Akonadi::ETMCalendar::Ptr &calendar,
 
  309                                        const Todo::Ptr &todo,
 
  310                                        const QDate &limitDate,
 
  313   if ( !todo->isCompleted() || todo->completed().date() >= limitDate ) {
 
  318   if ( checkedUids.
contains( todo->uid() ) ) {
 
  320     kWarning() << 
"To-do hierarchy loop detected!";
 
  324   checkedUids.
append( todo->uid() );
 
  325   KCalCore::Incidence::List childs = calendar->childIncidences( todo->uid() );
 
  326   foreach ( 
const KCalCore::Incidence::Ptr &incidence, childs ) {
 
  327     const Todo::Ptr t = incidence.dynamicCast<KCalCore::Todo>();
 
  328     if ( t && !isSubTreeComplete( calendar, t, limitDate, checkedUids ) ) {
 
void runAuto(const Akonadi::ETMCalendar::Ptr &calendar, Akonadi::IncidenceChanger *changer, QWidget *widget, bool withGUI)
Delete or archive events. 
bool contains(const QString &str, Qt::CaseSensitivity cs) const
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 ...
void append(const T &value)
QDate addMonths(int nmonths) const
CALENDARSUPPORT_EXPORT KCalCore::Incidence::List incidences(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
static KCalPrefs * instance()
Get instance of KCalPrefs. 
QDate addDays(int ndays) const
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()