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()