Commit fff4366f authored by Claudio Cambra's avatar Claudio Cambra
Browse files

Properly handle parent task deletion, preventing crashing on modifying orphaned child task

parent 709a7a99
Pipeline #92983 passed with stage
in 4 minutes and 21 seconds
......@@ -660,8 +660,54 @@ void CalendarManager::editIncidence(IncidenceWrapper *incidenceWrapper)
});
}
void CalendarManager::deleteIncidence(KCalendarCore::Incidence::Ptr incidence)
bool CalendarManager::hasChildren(KCalendarCore::Incidence::Ptr incidence)
{
return !m_calendar->childIncidences(incidence->uid()).isEmpty();
}
void CalendarManager::deleteAllChildren(KCalendarCore::Incidence::Ptr incidence)
{
auto allChildren = m_calendar->childIncidences(incidence->uid());
for (auto child : allChildren) {
if (!m_calendar->childIncidences(child->uid()).isEmpty()) {
deleteAllChildren(child);
}
}
for (auto child : allChildren) {
m_calendar->deleteIncidence(child);
}
}
void CalendarManager::deleteIncidence(KCalendarCore::Incidence::Ptr incidence, bool deleteChildren)
{
auto directChildren = m_calendar->childIncidences(incidence->uid());
if (!directChildren.isEmpty()) {
if (deleteChildren) {
m_changer->startAtomicOperation(i18n("Delete task and its sub-tasks"));
deleteAllChildren(incidence);
} else {
m_changer->startAtomicOperation(i18n("Delete task and make sub-tasks independent"));
for (auto child : directChildren) {
for (auto instance : m_calendar->instances(child)) {
KCalendarCore::Incidence::Ptr oldInstance(instance->clone());
instance->setRelatedTo(QString());
m_changer->modifyIncidence(m_calendar->item(instance), oldInstance);
}
KCalendarCore::Incidence::Ptr oldInc(child->clone());
child->setRelatedTo(QString());
m_changer->modifyIncidence(m_calendar->item(child), oldInc);
}
}
m_calendar->deleteIncidence(incidence);
m_changer->endAtomicOperation();
return;
}
m_calendar->deleteIncidence(incidence);
}
......
......@@ -72,7 +72,9 @@ public:
Q_INVOKABLE void addIncidence(IncidenceWrapper *incidenceWrapper);
Q_INVOKABLE void editIncidence(IncidenceWrapper *incidenceWrapper);
Q_INVOKABLE void deleteIncidence(KCalendarCore::Incidence::Ptr incidence);
Q_INVOKABLE bool hasChildren(KCalendarCore::Incidence::Ptr incidence);
void deleteAllChildren(KCalendarCore::Incidence::Ptr incidence);
Q_INVOKABLE void deleteIncidence(KCalendarCore::Incidence::Ptr incidence, bool deleteChildren = false);
Q_INVOKABLE QVariantMap getCollectionDetails(QVariant collectionId);
Q_INVOKABLE void setCollectionColor(qint64 collectionId, QColor color);
Q_INVOKABLE QVariant getIncidenceSubclassed(KCalendarCore::Incidence::Ptr incidencePtr);
......
......@@ -13,8 +13,10 @@ Kirigami.OverlaySheet {
signal addException(date exceptionDate, var incidenceWrapper)
signal addRecurrenceEndDate(date endDate, var incidenceWrapper)
signal deleteIncidence(var incidencePtr)
signal deleteIncidenceWithChildren(var incidencePtr)
property var incidenceWrapper
property bool incidenceHasChildren: incidenceWrapper !== undefined ? CalendarManager.hasChildren(incidenceWrapper.incidencePtr) : false
property date deleteDate
header: Kirigami.Heading {
......@@ -24,7 +26,12 @@ Kirigami.OverlaySheet {
footer: Loader {
active: incidenceWrapper !== undefined
sourceComponent: QQC2.DialogButtonBox {
sourceComponent: RowLayout {
spacing: Kirigami.Units.smallSpacing
Item {
Layout.fillWidth: true
}
QQC2.Button {
icon.name: "deletecell"
......@@ -50,20 +57,26 @@ Kirigami.OverlaySheet {
}
QQC2.Button {
icon.name: "delete"
text: incidenceWrapper.recurrenceData.type > 0 ? i18n("Delete All") : i18n("Delete")
icon.name: "group-delete"
text: i18n("Delete Only This")
visible: deleteIncidenceSheet.incidenceHasChildren && incidenceWrapper.recurrenceData.type === 0
onClicked: deleteIncidence(incidenceWrapper.incidencePtr)
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
}
QQC2.Button {
icon.name: "delete"
text: deleteIncidenceSheet.incidenceHasChildren || incidenceWrapper.recurrenceData.type > 0 ? i18n("Delete All") : i18n("Delete")
onClicked: deleteIncidenceSheet.incidenceHasChildren ? deleteIncidenceWithChildren(incidenceWrapper.incidencePtr) : deleteIncidence(incidenceWrapper.incidencePtr)
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
}
QQC2.Button {
icon.name: "dialog-cancel"
text: i18n("Cancel")
onClicked: deleteIncidenceSheet.close()
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.DestructiveRole
}
onRejected: deleteIncidenceSheet.close()
}
}
......@@ -83,15 +96,15 @@ Kirigami.OverlaySheet {
QQC2.Label {
Layout.fillWidth: true
text: i18n("Do you really want to delete item: \"%1\"?", incidenceWrapper.summary)
visible: incidenceWrapper.recurrenceData.type === 0
wrapMode: Text.WordWrap
}
QQC2.Label {
Layout.fillWidth: true
text: i18n("The calendar item \"%1\" recurs over multiple dates. Do you want to delete the selected occurrence on %2, also future occurrences, or all of its occurrences?", incidenceWrapper.summary, deleteDate.toLocaleDateString(Qt.locale()))
visible: incidenceWrapper.recurrenceData.type > 0
text: if(incidenceWrapper.recurrenceData.type === 0 && !deleteIncidenceSheet.incidenceHasChildren) {
return i18n("Do you want to delete item: \"%1\"?", incidenceWrapper.summary)
} else if(incidenceWrapper.recurrenceData.type === 0 && deleteIncidenceSheet.incidenceHasChildren) {
return i18n("Item \"%1\" has sub-items. Do you want to delete all related items, or just the currently selected item?", incidenceWrapper.summary)
} else if (incidenceWrapper.recurrenceData.type > 0 && deleteIncidenceSheet.incidenceHasChildren) {
return i18n("The calendar item \"%1\" recurs over multiple dates. This item also has sub-items.\n\nDo you want to delete the selected occurrence on %2, also future occurrences, or all of its occurrences?\n\nDeleting all will also delete sub-items!", incidenceWrapper.summary, deleteDate.toLocaleDateString(Qt.locale()))
} else if (incidenceWrapper.recurrenceData.type > 0) {
return i18n("The calendar item \"%1\" recurs over multiple dates. Do you want to delete the selected occurrence on %2, also future occurrences, or all of its occurrences?", incidenceWrapper.summary, deleteDate.toLocaleDateString(Qt.locale()))
}
wrapMode: Text.WordWrap
}
}
......
......@@ -661,6 +661,10 @@ Kirigami.ApplicationWindow {
CalendarManager.deleteIncidence(incidencePtr);
deleteIncidenceSheet.close();
}
onDeleteIncidenceWithChildren: {
CalendarManager.deleteIncidence(incidencePtr, true);
deleteIncidenceSheet.close();
}
}
Component {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment