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

calendarsupport

  • sources
  • kde-4.14
  • 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 <KLocalizedString>
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  // There is no KIO::NetAccess availabe for Windows CE
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";
252  QFile::remove( tmpFileName );
253  return;
254  }
255  // Merge with events to be archived.
256  archiveStore.setFileName( archiveFile );
257  if ( !archiveStore.load() ) {
258  kDebug() << "Can't merge with archive file";
259  QFile::remove( tmpFileName );
260  return;
261  }
262  } else {
263  archiveFile = tmpFileName;
264  }
265 
266  // Save archive calendar
267  if ( !archiveStore.save() ) {
268  QString errmess;
269  if ( format->exception() ) {
270  errmess = Stringify::errorMessage( *format->exception() );
271  } else {
272  errmess = i18nc( "save failure cause unknown", "Reason unknown" );
273  }
274  KMessageBox::error( widget, i18n( "Cannot write archive file %1. %2",
275  archiveStore.fileName(), errmess ) );
276  QFile::remove( tmpFileName );
277  return;
278  }
279 
280  // Upload if necessary
281  KUrl srcUrl;
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() ) );
287  QFile::remove( tmpFileName );
288  return;
289  }
290  }
291 
292  KIO::NetAccess::removeTempFile( archiveFile );
293  QFile::remove( tmpFileName );
294 
295  // We don't want it to ask to send invitations for each incidence.
296  changer->startAtomicOperation( i18n( "Archiving events" ) );
297 
298  // Delete archived events from calendar
299  Akonadi::Item::List items = calendar->itemList( incidences );
300  foreach ( const Akonadi::Item &item, items ) {
301  changer->deleteIncidence( item, widget );
302  } // TODO: emit only after hearing back from incidence changer
303  changer->endAtomicOperation();
304 
305  emit eventsDeleted();
306 }
307 
308 bool EventArchiver::isSubTreeComplete( const Akonadi::ETMCalendar::Ptr &calendar,
309  const Todo::Ptr &todo,
310  const QDate &limitDate,
311  QStringList checkedUids ) const
312 {
313  if ( !todo->isCompleted() || todo->completed().date() >= limitDate ) {
314  return false;
315  }
316 
317  // This QList is only to prevent infinit recursion
318  if ( checkedUids.contains( todo->uid() ) ) {
319  // Probably will never happen, calendar.cpp checks for this
320  kWarning() << "To-do hierarchy loop detected!";
321  return false;
322  }
323 
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 ) ) {
329  return false;
330  }
331  }
332 
333  return true;
334 }
335 
QWidget
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
QFile::remove
bool remove()
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
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:78
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:124
utils.h
QList::append
void append(const T &value)
QDate::addMonths
QDate addMonths(int nmonths) const
QObject
QDate
eventarchiver.h
QString
CalendarSupport::EventArchiver::eventsDeleted
void eventsDeleted()
CalendarSupport::incidences
CALENDARSUPPORT_EXPORT KCalCore::Incidence::List incidences(const QMimeData *mimeData, const KDateTime::Spec &timeSpec)
Definition: utils.cpp:377
CalendarSupport::KCalPrefs::instance
static KCalPrefs * instance()
Get instance of KCalPrefs.
Definition: kcalprefs.cpp:77
QStringList
QLatin1String
QDate::currentDate
QDate currentDate()
QDate::addDays
QDate addDays(int ndays) const
CalendarSupport::EventArchiver::~EventArchiver
virtual ~EventArchiver()
Definition: eventarchiver.cpp:72
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:360
CalendarSupport::KCalPrefs::timeSpec
KDateTime::Spec timeSpec()
Definition: kcalprefs.cpp:110
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:31:15 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
  • pimprint

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