• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

calendarsupport

  • sources
  • kde-4.12
  • kdepim
  • calendarsupport
eventarchiver.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
3  Copyright (c) 2004 David Faure <faure@kde.org>
4  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of Qt, and distribute the resulting executable,
22  without including the source code for Qt in the source distribution.
23 */
24 
25 #include "eventarchiver.h"
26 
27 #include "kcalprefs.h"
28 #include "utils.h"
29 
30 #include <Akonadi/Calendar/IncidenceChanger>
31 
32 #include <KCalCore/ICalFormat>
33 #include <KCalCore/FileStorage>
34 #include <KCalCore/MemoryCalendar>
35 
36 #include <KCalUtils/Stringify>
37 
38 #include <KDebug>
39 #include <KGlobal>
40 #include <KLocale>
41 #include <KMessageBox>
42 #include <KTemporaryFile>
43 #include <KIO/NetAccess>
44 
45 using namespace KCalCore;
46 using namespace KCalUtils;
47 using namespace CalendarSupport;
48 
49 class GroupwareScoppedDisabler {
50 public:
51  GroupwareScoppedDisabler(Akonadi::IncidenceChanger *changer) : m_changer(changer)
52  {
53  m_wasEnabled = m_changer->groupwareCommunication();
54  m_changer->setGroupwareCommunication(false);
55  }
56 
57  ~GroupwareScoppedDisabler()
58  {
59  m_changer->setGroupwareCommunication(m_wasEnabled);
60  }
61 
62  bool m_wasEnabled;
63  Akonadi::IncidenceChanger *m_changer;
64 };
65 
66 
67 EventArchiver::EventArchiver( QObject *parent )
68  : QObject( parent )
69 {
70 }
71 
72 EventArchiver::~EventArchiver()
73 {
74 }
75 
76 void EventArchiver::runOnce( const Akonadi::ETMCalendar::Ptr &calendar,
77  Akonadi::IncidenceChanger *changer,
78  const QDate &limitDate, QWidget *widget )
79 {
80  run( calendar, changer, limitDate, widget, true, true );
81 }
82 
83 void EventArchiver::runAuto( const Akonadi::ETMCalendar::Ptr &calendar,
84  Akonadi::IncidenceChanger *changer,
85  QWidget *widget, bool withGUI )
86 {
87  QDate limitDate( QDate::currentDate() );
88  const int expiryTime = KCalPrefs::instance()->mExpiryTime;
89  switch ( KCalPrefs::instance()->mExpiryUnit ) {
90  case KCalPrefs::UnitDays: // Days
91  limitDate = limitDate.addDays( -expiryTime );
92  break;
93  case KCalPrefs::UnitWeeks: // Weeks
94  limitDate = limitDate.addDays( -expiryTime * 7 );
95  break;
96  case KCalPrefs::UnitMonths: // Months
97  limitDate = limitDate.addMonths( -expiryTime );
98  break;
99  default:
100  return;
101  }
102  run( calendar, changer, limitDate, widget, withGUI, false );
103 }
104 
105 void EventArchiver::run( const Akonadi::ETMCalendar::Ptr &calendar,
106  Akonadi::IncidenceChanger *changer,
107  const QDate &limitDate, QWidget *widget,
108  bool withGUI, bool errorIfNone )
109 {
110  GroupwareScoppedDisabler disabler(changer); // Disables groupware communication temporarily
111 
112  // We need to use rawEvents, otherwise events hidden by filters will not be archived.
113  KCalCore::Event::List events;
114  KCalCore::Todo::List todos;
115  KCalCore::Journal::List journals;
116 
117  if ( KCalPrefs::instance()->mArchiveEvents ) {
118  events = calendar->rawEvents(
119  QDate( 1769, 12, 1 ),
120  // #29555, also advertised by the "limitDate not included" in the class docu
121  limitDate.addDays( -1 ),
122  CalendarSupport::KCalPrefs::instance()->timeSpec(),
123  true );
124  }
125  if ( KCalPrefs::instance()->mArchiveTodos ) {
126  KCalCore::Todo::List rawTodos = calendar->rawTodos();
127 
128  foreach( const KCalCore::Todo::Ptr &todo, rawTodos ) {
129  Q_ASSERT( todo );
130  if ( isSubTreeComplete( calendar, todo, limitDate ) ) {
131  todos.append( todo );
132  }
133  }
134  }
135 
136  const KCalCore::Incidence::List incidences = calendar->mergeIncidenceList( events, todos, journals );
137 
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 ) ),
145  QLatin1String("ArchiverNoIncidences") );
146  }
147  return;
148  }
149 
150  switch ( KCalPrefs::instance()->mArchiveAction ) {
151  case KCalPrefs::actionDelete:
152  deleteIncidences( changer, limitDate, widget, calendar->itemList( incidences ), withGUI );
153  break;
154  case KCalPrefs::actionArchive:
155  archiveIncidences( calendar, changer, limitDate, widget, incidences, withGUI );
156  break;
157  }
158 }
159 
160 void EventArchiver::deleteIncidences( Akonadi::IncidenceChanger *changer,
161  const QDate &limitDate, QWidget *widget,
162  const Akonadi::Item::List &items, bool withGUI )
163 {
164  QStringList incidenceStrs;
165  Akonadi::Item::List::ConstIterator it;
166  Akonadi::Item::List::ConstIterator end( items.constEnd() );
167  for ( it = items.constBegin(); it != end; ++it ) {
168  incidenceStrs.append( CalendarSupport::incidence( *it )->summary() );
169  }
170 
171  if ( withGUI ) {
172  const int result = KMessageBox::warningContinueCancelList(
173  widget,
174  i18n( "Delete all items before %1 without saving?\n"
175  "The following items will be deleted:",
176  KGlobal::locale()->formatDate( limitDate ) ),
177  incidenceStrs,
178  i18n( "Delete Old Items" ), KStandardGuiItem::del() );
179  if ( result != KMessageBox::Continue ) {
180  return;
181  }
182  }
183 
184  changer->deleteIncidences( items, widget );
185 
186  // TODO: emit only after hearing back from incidence changer
187  emit eventsDeleted();
188 }
189 
190 void EventArchiver::archiveIncidences( const Akonadi::ETMCalendar::Ptr &calendar,
191  Akonadi::IncidenceChanger *changer,
192  const QDate &limitDate, QWidget *widget,
193  const KCalCore::Incidence::List &incidences, bool withGUI )
194 {
195  Q_UNUSED( limitDate );
196  Q_UNUSED( withGUI );
197 
198  FileStorage storage( calendar );
199 
200  QString tmpFileName;
201  // KSaveFile cannot be called with an open File Handle on Windows.
202  // So we use KTemporaryFile only to generate a unique filename
203  // and then close/delete the file again. This file must be deleted
204  // here.
205  {
206  KTemporaryFile tmpFile;
207  tmpFile.open();
208  tmpFileName = tmpFile.fileName();
209  }
210  // Save current calendar to disk
211  storage.setFileName( tmpFileName );
212  if ( !storage.save() ) {
213  kDebug() << "Can't save calendar to temp file";
214  return;
215  }
216 
217  // Duplicate current calendar by loading in new calendar object
218  MemoryCalendar::Ptr archiveCalendar(
219  new MemoryCalendar( CalendarSupport::KCalPrefs::instance()->timeSpec() ) );
220 
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";
227  QFile::remove( tmpFileName );
228  return;
229  }
230 
231  // Strip active events from calendar so that only events to be archived
232  // remain. This is not really efficient, but there is no other easy way.
233  QStringList uids;
234  Incidence::List allIncidences = archiveCalendar->rawIncidences();
235  foreach ( const KCalCore::Incidence::Ptr &incidence, incidences ) {
236  uids.append( incidence->uid() );
237  }
238  foreach ( const KCalCore::Incidence::Ptr &incidence, allIncidences ) {
239  if ( !uids.contains( incidence->uid() ) ) {
240  archiveCalendar->deleteIncidence( incidence );
241  }
242  }
243 
244  // Get or create the archive file
245  KUrl archiveURL( KCalPrefs::instance()->mArchiveFile );
246  QString archiveFile;
247 
248 #ifndef Q_OS_WINCE
249  // There is no KIO::NetAccess availabe for Windows CE
250  if ( KIO::NetAccess::exists( archiveURL, KIO::NetAccess::SourceSide, widget ) ) {
251  if( !KIO::NetAccess::download( archiveURL, archiveFile, widget ) ) {
252  kDebug() << "Can't download archive file";
253  QFile::remove( tmpFileName );
254  return;
255  }
256  // Merge with events to be archived.
257  archiveStore.setFileName( archiveFile );
258  if ( !archiveStore.load() ) {
259  kDebug() << "Can't merge with archive file";
260  QFile::remove( tmpFileName );
261  return;
262  }
263  } else {
264  archiveFile = tmpFileName;
265  }
266 #else
267  archiveFile = archiveURL.toLocalFile();
268  archiveStore.setFileName( archiveFile );
269 #endif // Q_OS_WINCE
270 
271  // Save archive calendar
272  if ( !archiveStore.save() ) {
273  QString errmess;
274  if ( format->exception() ) {
275  errmess = Stringify::errorMessage( *format->exception() );
276  } else {
277  errmess = i18nc( "save failure cause unknown", "Reason unknown" );
278  }
279  KMessageBox::error( widget, i18n( "Cannot write archive file %1. %2",
280  archiveStore.fileName(), errmess ) );
281  QFile::remove( tmpFileName );
282  return;
283  }
284 
285 #ifndef Q_OS_WINCE
286  // Upload if necessary
287  KUrl srcUrl;
288  srcUrl.setPath( archiveFile );
289  if ( srcUrl != archiveURL ) {
290  if ( !KIO::NetAccess::upload( archiveFile, archiveURL, widget ) ) {
291  KMessageBox::error( widget, i18n( "Cannot write archive. %1",
292  KIO::NetAccess::lastErrorString() ) );
293  QFile::remove( tmpFileName );
294  return;
295  }
296  }
297 
298  KIO::NetAccess::removeTempFile( archiveFile );
299 #endif // Q_OS_WINCE
300  QFile::remove( tmpFileName );
301 
302  // We don't want it to ask to send invitations for each incidence.
303  changer->startAtomicOperation( i18n( "Archiving events" ) );
304 
305  // Delete archived events from calendar
306  Akonadi::Item::List items = calendar->itemList( incidences );
307  foreach ( const Akonadi::Item &item, items ) {
308  changer->deleteIncidence( item, widget );
309  } // TODO: emit only after hearing back from incidence changer
310  changer->endAtomicOperation();
311 
312  emit eventsDeleted();
313 }
314 
315 bool EventArchiver::isSubTreeComplete( const Akonadi::ETMCalendar::Ptr &calendar,
316  const Todo::Ptr &todo,
317  const QDate &limitDate,
318  QStringList checkedUids ) const
319 {
320  if ( !todo->isCompleted() || todo->completed().date() >= limitDate ) {
321  return false;
322  }
323 
324  // This QList is only to prevent infinit recursion
325  if ( checkedUids.contains( todo->uid() ) ) {
326  // Probably will never happen, calendar.cpp checks for this
327  kWarning() << "To-do hierarchy loop detected!";
328  return false;
329  }
330 
331  checkedUids.append( todo->uid() );
332  KCalCore::Incidence::List childs = calendar->childIncidences( todo->uid() );
333  foreach ( const KCalCore::Incidence::Ptr &incidence, childs ) {
334  const Todo::Ptr t = incidence.dynamicCast<KCalCore::Todo>();
335  if ( t && !isSubTreeComplete( calendar, t, limitDate, checkedUids ) ) {
336  return false;
337  }
338  }
339 
340  return true;
341 }
342 
343 #include "eventarchiver.moc"
CalendarSupport::KCalPrefsBase::UnitWeeks
Definition: kcalprefs_base.h:18
CalendarSupport::KCalPrefsBase::UnitDays
Definition: kcalprefs_base.h:18
CalendarSupport::EventArchiver::runAuto
void runAuto(const Akonadi::ETMCalendar::Ptr &calendar, Akonadi::IncidenceChanger *changer, QWidget *widget, bool withGUI)
Delete or archive events.
Definition: eventarchiver.cpp:83
QWidget
CalendarSupport::KCalPrefsBase::actionDelete
Definition: kcalprefs_base.h:19
QObject
CalendarSupport::incidence
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 ...
Definition: utils.cpp:75
kcalprefs.h
CalendarSupport::todo
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 ...
Definition: utils.cpp:121
utils.h
CalendarSupport::KCalPrefsBase::actionArchive
Definition: kcalprefs_base.h:19
eventarchiver.h
CalendarSupport::EventArchiver::eventsDeleted
void eventsDeleted()
CalendarSupport::incidences
CALENDARSUPPORT_EXPORT KCalCore::Incidence::List incidences(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
Definition: utils.cpp:374
CalendarSupport::KCalPrefsBase::mArchiveTodos
bool mArchiveTodos
Definition: kcalprefs_base.h:782
CalendarSupport::KCalPrefs::instance
static KCalPrefs * instance()
Get instance of KCalPrefs.
Definition: kcalprefs.cpp:75
CalendarSupport::KCalPrefsBase::mExpiryTime
int mExpiryTime
Definition: kcalprefs_base.h:778
CalendarSupport::EventArchiver::~EventArchiver
virtual ~EventArchiver()
Definition: eventarchiver.cpp:72
CalendarSupport::KCalPrefsBase::UnitMonths
Definition: kcalprefs_base.h:18
CalendarSupport::EventArchiver::runOnce
void runOnce(const Akonadi::ETMCalendar::Ptr &calendar, Akonadi::IncidenceChanger *changer, const QDate &limitDate, QWidget *widget)
Delete or archive events once.
Definition: eventarchiver.cpp:76
CalendarSupport::todos
CALENDARSUPPORT_EXPORT KCalCore::Todo::List todos(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
Definition: utils.cpp:357
CalendarSupport::KCalPrefs::timeSpec
KDateTime::Spec timeSpec()
Definition: kcalprefs.cpp:108
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:54:59 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

calendarsupport

Skip menu "calendarsupport"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal