Commit 867ccc65 authored by Claudio Cambra's avatar Claudio Cambra
Browse files

Add drag/drop for tasks to change collections

parent ed990074
Pipeline #113829 passed with stage
in 5 minutes
......@@ -51,6 +51,7 @@
#include <KCheckableProxyModel>
#include <KLocalizedString>
#include <QApplication>
#include <QDebug>
#include <QPointer>
#include <QRandomGenerator>
#include <etmcalendar.h>
......@@ -707,13 +708,7 @@ void CalendarManager::editIncidence(IncidenceWrapper *incidenceWrapper)
return;
}
Akonadi::Collection newCollection(incidenceWrapper->collectionId());
modifiedItem.setParentCollection(newCollection);
auto job = new Akonadi::ItemMoveJob(modifiedItem, newCollection);
// Add some type of check here?
connect(job, &KJob::result, job, [=]() {
qCDebug(KALENDAR_LOG) << job->error();
});
changeIncidenceCollection(modifiedItem, incidenceWrapper->collectionId());
}
void CalendarManager::updateIncidenceDates(IncidenceWrapper *incidenceWrapper, int startOffset, int endOffset, int occurrences, const QDateTime &occurrenceDate)
......@@ -847,6 +842,47 @@ void CalendarManager::deleteIncidence(KCalendarCore::Incidence::Ptr incidence, b
m_calendar->deleteIncidence(incidence);
}
void CalendarManager::changeIncidenceCollection(KCalendarCore::Incidence::Ptr incidence, qint64 collectionId)
{
KCalendarCore::Incidence::Ptr incidenceClone(incidence->clone());
Akonadi::Item modifiedItem = m_calendar->item(incidence->instanceIdentifier());
modifiedItem.setPayload<KCalendarCore::Incidence::Ptr>(incidenceClone);
if (modifiedItem.parentCollection().id() != collectionId) {
changeIncidenceCollection(modifiedItem, collectionId);
}
}
void CalendarManager::changeIncidenceCollection(Akonadi::Item item, qint64 collectionId)
{
if (item.parentCollection().id() == collectionId) {
return;
}
Q_ASSERT(item.hasPayload<KCalendarCore::Incidence::Ptr>());
Akonadi::Collection newCollection(collectionId);
item.setParentCollection(newCollection);
auto job = new Akonadi::ItemMoveJob(item, newCollection);
// Add some type of check here?
connect(job, &KJob::result, job, [=]() {
qCDebug(KALENDAR_LOG) << job->error();
if (!job->error()) {
const auto allChildren = m_calendar->childIncidences(item.id());
for (const auto &child : allChildren) {
changeIncidenceCollection(m_calendar->item(child), collectionId);
}
auto parent = item.payload<KCalendarCore::Incidence::Ptr>()->relatedTo();
if (!parent.isEmpty()) {
changeIncidenceCollection(m_calendar->item(parent), collectionId);
}
}
});
}
QVariantMap CalendarManager::getCollectionDetails(QVariant collectionId)
{
QVariantMap collectionDetails;
......
......@@ -86,6 +86,8 @@ public:
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 void changeIncidenceCollection(KCalendarCore::Incidence::Ptr incidence, qint64 collectionId);
void changeIncidenceCollection(Akonadi::Item item, qint64 collectionId);
Q_INVOKABLE QVariantMap getCollectionDetails(QVariant collectionId);
Q_INVOKABLE void setCollectionColor(qint64 collectionId, QColor color);
Q_INVOKABLE QVariant getIncidenceSubclassed(KCalendarCore::Incidence::Ptr incidencePtr);
......
......@@ -820,6 +820,10 @@ Kirigami.Page {
onDropped: if(viewLoader.isCurrentItem) {
let incidenceWrapper = Qt.createQmlObject('import org.kde.kalendar 1.0; IncidenceWrapper {id: incidence}', incidenceDropArea, "incidence");
/* So when we drop the entire incidence card somewhere, we are dropping the delegate with object name "incidenceDelegate".
* However, when we are simply resizing, we are actually dropping the specific mouseArea within the delegate that handles
* the dragging for the incidence's bottom edge which has name "endDtResizeMouseArea". Hence why we check the object names
*/
if(drop.source.objectName === "incidenceDelegate") {
incidenceWrapper.incidenceItem = Kalendar.CalendarManager.incidenceItem(drop.source.incidencePtr);
......
......@@ -498,6 +498,7 @@ Kirigami.OverlayDrawer {
(Kirigami.Units.largeSpacing * model.kDescendantLevel) + (Kirigami.Units.iconSizes.smallMedium * (model.kDescendantLevel - 1))
separatorVisible: false
enabled: !sidebar.collapsed
highlighted: incidenceDropArea.containsDrag
leading: Kirigami.Icon {
implicitWidth: Kirigami.Units.iconSizes.smallMedium
......@@ -531,6 +532,20 @@ Kirigami.OverlayDrawer {
anchors.fill: parent
onDeleteCalendar: sidebar.deleteCalendar(collectionId, collectionDetails)
DropArea {
id: incidenceDropArea
anchors.fill: parent
z: 9999
onDropped: if(drop.source.objectName === "taskDelegate") {
CalendarManager.changeIncidenceCollection(drop.source.incidencePtr, calendarItemMouseArea.collectionId);
const pos = mapToItem(applicationWindow().contentItem, x, y);
drop.source.caughtX = pos.x;
drop.source.caughtY = pos.y;
drop.source.caught = true;
}
}
}
}
}
......
......@@ -30,6 +30,7 @@ TreeListView {
property int showCompleted: Kalendar.TodoSortFilterProxyModel.ShowAll
property int sortBy: Kalendar.TodoSortFilterProxyModel.SummaryColumn
property bool ascendingOrder: false
property bool dragDropEnabled: true
property alias model: todoModel
readonly property bool isDark: LabelUtils.isDarkColor(Kirigami.Theme.backgroundColor)
......@@ -130,6 +131,7 @@ TreeListView {
}
delegate: BasicTreeItem {
id: listItem
objectName: "taskDelegate"
Layout.fillWidth: true
Binding {
......@@ -144,13 +146,68 @@ TreeListView {
activeBackgroundColor: LabelUtils.getIncidenceBackgroundColor(model.color, root.isDark)
onActiveBackgroundColorChanged: activeBackgroundColor.a = 0.15
property alias mouseArea: mouseArea
property var incidencePtr: model.incidencePtr
property date occurrenceDate: model.startTime
property date occurrenceEndDate: model.endTime
property bool repositionAnimationEnabled: false
property bool caught: false
property real caughtX: x
property real caughtY: y
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: mouseArea.mouseX
Drag.hotSpot.y: mouseArea.mouseY
Behavior on x {
enabled: repositionAnimationEnabled
NumberAnimation {
duration: Kirigami.Units.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on y {
enabled: repositionAnimationEnabled
NumberAnimation {
duration: Kirigami.Units.shortDuration
easing.type: Easing.OutCubic
}
}
states: [
State {
when: listItem.mouseArea.drag.active
ParentChange { target: listItem; parent: applicationWindow().contentItem }
PropertyChanges { target: listItem; highlighted: true; z: 9999 }
PropertyChanges { target: applicationWindow().contentItem; clip: false }
PropertyChanges { target: applicationWindow().globalDrawer; z: -1 }
},
State {
when: listItem.caught
ParentChange { target: listItem; parent: root }
PropertyChanges {
target: listItem
repositionAnimationEnabled: true
x: caughtX
y: caughtY
}
}
]
contentItem: IncidenceMouseArea {
id: mouseArea
implicitWidth: todoItemContents.implicitWidth
implicitHeight: Kirigami.Settings.isMobile ?
todoItemContents.implicitHeight + Kirigami.Units.largeSpacing : todoItemContents.implicitHeight + Kirigami.Units.smallSpacing
incidenceData: model
collectionId: model.collectionId
propagateComposedEvents: true
preventStealing: !Kirigami.Settings.tabletMode && !Kirigami.Settings.isMobile
drag.target: !Kirigami.Settings.isMobile && !model.isReadOnly && root.dragDropEnabled ? listItem : undefined
onReleased: listItem.Drag.drop()
onViewClicked: root.viewTodo(model), listItem.clicked()
onEditClicked: root.editTodo(model.incidencePtr)
......@@ -158,6 +215,8 @@ TreeListView {
onTodoCompletedClicked: model.checked = model.checked === 0 ? 2 : 0
onAddSubTodoClicked: root.addSubTodo(parentWrapper)
onClicked: root.viewTodo(model)
GridLayout {
id: todoItemContents
......@@ -266,7 +325,5 @@ TreeListView {
}
}
}
onClicked: root.viewTodo(model)
}
}
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