diff --git a/src/presentation/contextpagemodel.cpp b/src/presentation/contextpagemodel.cpp --- a/src/presentation/contextpagemodel.cpp +++ b/src/presentation/contextpagemodel.cpp @@ -158,10 +158,28 @@ return false; } + using namespace std::placeholders; + auto associate = std::function(); + auto dissociate = std::function(); + auto parentTitle = QString(); + + if (parentTask) { + associate = std::bind(&Domain::TaskRepository::associate, m_taskRepository, parentTask, _1); + dissociate = [] (Domain::Task::Ptr) -> KJob* { return Q_NULLPTR; }; + parentTitle = parentTask->title(); + } else { + associate = std::bind(&Domain::ContextRepository::associate, m_contextRepository, m_context, _1); + dissociate = std::bind(&Domain::TaskRepository::dissociate, m_taskRepository, _1); + parentTitle = m_context->name(); + } + foreach(const Domain::Artifact::Ptr &droppedArtifact, droppedArtifacts) { auto childTask = droppedArtifact.objectCast(); - const auto job = m_taskRepository->associate(parentTask, childTask); - installHandler(job, tr("Cannot move task %1 as sub-task of %2").arg(childTask->title()).arg(parentTask->title())); + auto job = associate(childTask); + installHandler(job, tr("Cannot move task %1 as sub-task of %2").arg(childTask->title(), parentTitle)); + job = dissociate(childTask); + if (job) + installHandler(job, tr("Cannot dissociate task %1 from its parent").arg(childTask->title())); } return true; diff --git a/tests/units/presentation/contextpagemodeltest.cpp b/tests/units/presentation/contextpagemodeltest.cpp --- a/tests/units/presentation/contextpagemodeltest.cpp +++ b/tests/units/presentation/contextpagemodeltest.cpp @@ -637,6 +637,72 @@ QTest::qWait(150); QCOMPARE(errorHandler.m_message, QString("Cannot move task childTask2 as sub-task of A parent task: Foo")); } + + void shouldAssociateToContextWithNoParentWhenDroppingOnEmptyArea() + { + // GIVEN + + // One context + auto context = Domain::Context::Ptr::create(); + context->setName("Context"); + + // One top level task + auto topLevelTask = Domain::Task::Ptr::create(); + topLevelTask->setTitle("rootTask"); + auto topLevelProvider = Domain::QueryResultProvider::Ptr::create(); + auto topLevelResult = Domain::QueryResult::create(topLevelProvider); + topLevelProvider->append(topLevelTask); + + // Two tasks under the top level task + auto childTask1 = Domain::Task::Ptr::create(); + childTask1->setTitle("childTask1"); + childTask1->setDone(true); + auto childTask2 = Domain::Task::Ptr::create(); + childTask2->setTitle("childTask2"); + childTask2->setDone(false); + auto taskProvider = Domain::QueryResultProvider::Ptr::create(); + auto taskResult = Domain::QueryResult::create(taskProvider); + taskProvider->append(childTask1); + taskProvider->append(childTask2); + + Utils::MockObject contextQueriesMock; + contextQueriesMock(&Domain::ContextQueries::findTopLevelTasks).when(context).thenReturn(topLevelResult); + + Utils::MockObject contextRepositoryMock; + + Utils::MockObject taskQueriesMock; + taskQueriesMock(&Domain::TaskQueries::findChildren).when(topLevelTask).thenReturn(taskResult); + taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask1).thenReturn(Domain::QueryResult::Ptr()); + taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask2).thenReturn(Domain::QueryResult::Ptr()); + + Utils::MockObject taskRepositoryMock; + + Presentation::ContextPageModel page(context, + contextQueriesMock.getInstance(), + contextRepositoryMock.getInstance(), + taskQueriesMock.getInstance(), + taskRepositoryMock.getInstance()); + + auto model = page.centralListModel(); + + // WHEN + taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask1).thenReturn(new FakeJob(this)); + taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask2).thenReturn(new FakeJob(this)); + contextRepositoryMock(&Domain::ContextRepository::associate).when(context, childTask1).thenReturn(new FakeJob(this)); + contextRepositoryMock(&Domain::ContextRepository::associate).when(context, childTask2).thenReturn(new FakeJob(this)); + + auto data = new QMimeData; + data->setData("application/x-zanshin-object", "object"); + data->setProperty("objects", QVariant::fromValue(Domain::Artifact::List() << childTask1 << childTask2)); // both will be DnD on the empty part + model->dropMimeData(data, Qt::MoveAction, -1, -1, QModelIndex()); + + // THEN + QTest::qWait(150); + QVERIFY(taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask1).exactly(1)); + QVERIFY(taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask2).exactly(1)); + QVERIFY(contextRepositoryMock(&Domain::ContextRepository::associate).when(context, childTask1).exactly(1)); + QVERIFY(contextRepositoryMock(&Domain::ContextRepository::associate).when(context, childTask2).exactly(1)); + } }; QTEST_MAIN(ContextPageModelTest)