File indexing completed on 2024-05-12 05:10:50
0001 /* 0002 SPDX-FileCopyrightText: 2013 Sérgio Martins <iamsergio@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "todopurger.h" 0008 #include "calendarutils.h" 0009 #include "fetchjobcalendar.h" 0010 #include "todopurger_p.h" 0011 0012 #include <KCalendarCore/Todo> 0013 0014 #include <KLocalizedString> 0015 using namespace Akonadi; 0016 0017 TodoPurgerPrivate::TodoPurgerPrivate(TodoPurger *q) 0018 : q(q) 0019 { 0020 } 0021 0022 void TodoPurgerPrivate::onCalendarLoaded(bool success, const QString &message) 0023 { 0024 if (success) { 0025 deleteTodos(); 0026 } else { 0027 m_lastError = message; 0028 if (m_calendarOwnership) { 0029 m_calendar.clear(); 0030 } 0031 Q_EMIT q->todosPurged(false, 0, 0); 0032 } 0033 } 0034 0035 void TodoPurgerPrivate::onItemsDeleted(int changeId, const QList<Item::Id> &deletedItems, IncidenceChanger::ResultCode result, const QString &message) 0036 { 0037 if (changeId != m_currentChangeId) { 0038 return; // Not ours. 0039 } 0040 0041 m_lastError = message; 0042 if (m_calendarOwnership) { 0043 m_calendar.clear(); 0044 } 0045 Q_EMIT q->todosPurged(result == IncidenceChanger::ResultCodeSuccess, deletedItems.count(), m_ignoredItems); 0046 } 0047 0048 void TodoPurgerPrivate::deleteTodos() 0049 { 0050 if (!m_changer) { 0051 q->setIncidenceChager(new IncidenceChanger(this)); 0052 m_changer->setShowDialogsOnError(false); 0053 m_changer->setHistoryEnabled(false); 0054 } 0055 0056 const bool oldShowdialogs = m_changer->showDialogsOnError(); 0057 const bool oldGroupware = m_changer->groupwareCommunication(); 0058 m_changer->setShowDialogsOnError(false); 0059 m_changer->setGroupwareCommunication(false); 0060 0061 m_changer->startAtomicOperation(i18n("Purging completed to-dos")); 0062 const Akonadi::Item::List items = m_calendar->items(); 0063 Akonadi::Item::List toDelete; 0064 m_ignoredItems = 0; 0065 for (const Akonadi::Item &item : items) { 0066 KCalendarCore::Todo::Ptr todo = CalendarUtils::todo(item); 0067 0068 if (!todo || !todo->isCompleted()) { 0069 continue; 0070 } 0071 0072 if (treeIsDeletable(todo)) { 0073 toDelete.append(item); 0074 } else { 0075 m_ignoredItems++; 0076 } 0077 } 0078 0079 if (toDelete.isEmpty()) { 0080 if (m_calendarOwnership) { 0081 m_calendar.clear(); 0082 } 0083 Q_EMIT q->todosPurged(true, 0, m_ignoredItems); 0084 } else { 0085 m_currentChangeId = m_changer->deleteIncidences(toDelete); 0086 Q_ASSERT(m_currentChangeId > 0); 0087 } 0088 0089 m_changer->endAtomicOperation(); 0090 0091 m_changer->setShowDialogsOnError(oldShowdialogs); 0092 m_changer->setGroupwareCommunication(oldGroupware); 0093 } 0094 0095 bool TodoPurgerPrivate::treeIsDeletable(const KCalendarCore::Todo::Ptr &todo) 0096 { 0097 Q_ASSERT(todo); 0098 0099 if (!todo->isCompleted() || todo->isReadOnly()) { 0100 return false; 0101 } 0102 0103 const KCalendarCore::Incidence::List children = m_calendar->childIncidences(todo->uid()); 0104 if (children.isEmpty()) { 0105 return true; 0106 } 0107 0108 for (const KCalendarCore::Incidence::Ptr &child : children) { 0109 KCalendarCore::Todo::Ptr childTodo = child.dynamicCast<KCalendarCore::Todo>(); 0110 0111 if (!childTodo) { 0112 return false; // This never happens 0113 } 0114 0115 if (!treeIsDeletable(childTodo)) { 0116 return false; 0117 } 0118 } 0119 0120 return true; 0121 } 0122 0123 TodoPurger::TodoPurger(QObject *parent) 0124 : QObject(parent) 0125 , d(new TodoPurgerPrivate(this)) 0126 { 0127 } 0128 0129 TodoPurger::~TodoPurger() = default; 0130 0131 void TodoPurger::setIncidenceChager(IncidenceChanger *changer) 0132 { 0133 d->m_changer = changer; 0134 d->m_currentChangeId = -1; 0135 if (changer) { 0136 connect(changer, &IncidenceChanger::deleteFinished, d.get(), &TodoPurgerPrivate::onItemsDeleted); 0137 } 0138 } 0139 0140 void TodoPurger::setCalendar(const CalendarBase::Ptr &calendar) 0141 { 0142 d->m_calendar = calendar; 0143 d->m_calendarOwnership = calendar.isNull(); 0144 } 0145 0146 void TodoPurger::purgeCompletedTodos() 0147 { 0148 d->m_lastError.clear(); 0149 0150 if (d->m_calendar) { 0151 d->deleteTodos(); 0152 } else { 0153 d->m_calendar = FetchJobCalendar::Ptr(new FetchJobCalendar(this)); 0154 // clang-format off 0155 connect(d->m_calendar.data(), SIGNAL(loadFinished(bool,QString)), d.get(), SLOT(onCalendarLoaded(bool,QString))); 0156 // clang-format on 0157 } 0158 } 0159 0160 QString TodoPurger::lastError() const 0161 { 0162 return d->m_lastError; 0163 } 0164 0165 #include "moc_todopurger_p.cpp" 0166 0167 #include "moc_todopurger.cpp"