File indexing completed on 2024-06-02 05:33:00

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0003  * SPDX-FileCopyrightText: 2014 RĂ©mi Benoit <r3m1.benoit@gmail.com>
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "contextpagemodel.h"
0008 
0009 #include <QMimeData>
0010 
0011 #include <KLocalizedString>
0012 
0013 #include "domain/task.h"
0014 
0015 #include "presentation/querytreemodel.h"
0016 
0017 using namespace Presentation;
0018 
0019 ContextPageModel::ContextPageModel(const Domain::Context::Ptr &context,
0020                                    const Domain::ContextQueries::Ptr &contextQueries,
0021                                    const Domain::ContextRepository::Ptr &contextRepository,
0022                                    const Domain::TaskQueries::Ptr &taskQueries,
0023                                    const Domain::TaskRepository::Ptr &taskRepository,
0024                                    QObject *parent)
0025     : PageModel(parent),
0026       m_context(context),
0027       m_contextQueries(contextQueries),
0028       m_contextRepository(contextRepository),
0029       m_taskQueries(taskQueries),
0030       m_taskRepository(taskRepository)
0031 {
0032 
0033 }
0034 
0035 Domain::Context::Ptr ContextPageModel::context() const
0036 {
0037     return m_context;
0038 }
0039 
0040 Domain::Task::Ptr ContextPageModel::addItem(const QString &title, const QModelIndex &parentIndex)
0041 {
0042     const auto parentData = parentIndex.data(QueryTreeModelBase::ObjectRole);
0043     const auto parentTask = parentData.value<Domain::Task::Ptr>();
0044 
0045     auto task = Domain::Task::Ptr::create();
0046     task->setTitle(title);
0047 
0048     const auto job = parentTask ? m_taskRepository->createChild(task, parentTask)
0049                    : m_taskRepository->createInContext(task, m_context);
0050     installHandler(job, i18n("Cannot add task %1 in context %2", title, m_context->name()));
0051 
0052     return task;
0053 }
0054 
0055 void ContextPageModel::removeItem(const QModelIndex &index)
0056 {
0057     QVariant data = index.data(QueryTreeModelBase::ObjectRole);
0058     auto task = data.value<Domain::Task::Ptr>();
0059     const auto job = index.parent().isValid() ? m_taskRepository->dissociate(task)
0060                    : m_contextRepository->dissociate(m_context, task);
0061     installHandler(job, i18n("Cannot remove task %1 from context %2", task->title(), m_context->name()));
0062 }
0063 
0064 void ContextPageModel::promoteItem(const QModelIndex &index)
0065 {
0066     QVariant data = index.data(QueryTreeModelBase::ObjectRole);
0067     auto task = data.value<Domain::Task::Ptr>();
0068     Q_ASSERT(task);
0069     const auto job = m_taskRepository->promoteToProject(task);
0070     installHandler(job, i18n("Cannot promote task %1 to be a project", task->title()));
0071 }
0072 
0073 QAbstractItemModel *ContextPageModel::createCentralListModel()
0074 {
0075     auto query = [this] (const Domain::Task::Ptr &task) -> Domain::QueryResultInterface<Domain::Task::Ptr>::Ptr {
0076         if (!task)
0077             return m_contextQueries->findTopLevelTasks(m_context);
0078         else
0079             return m_taskQueries->findChildren(task);
0080     };
0081 
0082     auto flags = [] (const Domain::Task::Ptr &task) {
0083         Q_UNUSED(task);
0084         return Qt::ItemIsSelectable
0085              | Qt::ItemIsEnabled
0086              | Qt::ItemIsEditable
0087              | Qt::ItemIsDragEnabled
0088              | Qt::ItemIsUserCheckable
0089              | Qt::ItemIsDropEnabled;
0090     };
0091 
0092     auto data = [](const Domain::Task::Ptr &task, int role, const TaskExtraDataPtr &info) -> QVariant {
0093         return defaultTaskData(task, role, info);
0094     };
0095 
0096     auto fetchAdditionalInfo = [this](const QModelIndex &index, const Domain::Task::Ptr &task) {
0097         return fetchTaskExtraData(m_taskQueries, TaskExtraPart::Project, index, task);
0098     };
0099 
0100     auto setData = [this] (const Domain::Task::Ptr &task, const QVariant &value, int role) {
0101         if (role != Qt::EditRole && role != Qt::CheckStateRole)
0102             return false;
0103 
0104         const auto currentTitle = task->title();
0105         if (role == Qt::EditRole)
0106             task->setTitle(value.toString());
0107         else
0108             task->setDone(value.toInt() == Qt::Checked);
0109 
0110         const auto job = m_taskRepository->update(task);
0111         installHandler(job, i18n("Cannot modify task %1 in context %2", currentTitle, m_context->name()));
0112         return true;
0113     };
0114 
0115     auto drop = [this] (const QMimeData *mimeData, Qt::DropAction, const Domain::Task::Ptr &parentTask) {
0116         if (!mimeData->hasFormat(QStringLiteral("application/x-zanshin-object")))
0117             return false;
0118 
0119         auto droppedTasks = mimeData->property("objects").value<Domain::Task::List>();
0120         if (droppedTasks.isEmpty())
0121             return false;
0122 
0123         using namespace std::placeholders;
0124         auto associate = std::function<KJob*(Domain::Task::Ptr)>();
0125         auto dissociate = std::function<KJob*(Domain::Task::Ptr)>();
0126         auto parentTitle = QString();
0127 
0128         if (parentTask) {
0129             associate = std::bind(&Domain::TaskRepository::associate, m_taskRepository, parentTask, _1);
0130             dissociate = [] (Domain::Task::Ptr) -> KJob* { return nullptr; };
0131             parentTitle = parentTask->title();
0132         } else {
0133             associate = std::bind(&Domain::ContextRepository::associate, m_contextRepository, m_context, _1);
0134             dissociate = std::bind(&Domain::TaskRepository::dissociate, m_taskRepository, _1);
0135             parentTitle = m_context->name();
0136         }
0137 
0138         foreach(const Domain::Task::Ptr &childTask, droppedTasks) {
0139             auto job = associate(childTask);
0140             installHandler(job, i18n("Cannot move task %1 as sub-task of %2", childTask->title(), parentTitle));
0141             job = dissociate(childTask);
0142             if (job)
0143                 installHandler(job, i18n("Cannot dissociate task %1 from its parent", childTask->title()));
0144         }
0145 
0146         return true;
0147     };
0148 
0149     auto drag = [] (const Domain::Task::List &tasks) -> QMimeData* {
0150         if (tasks.isEmpty())
0151             return nullptr;
0152 
0153         auto data = new QMimeData();
0154         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0155         data->setProperty("objects", QVariant::fromValue(tasks));
0156         return data;
0157     };
0158 
0159     return new QueryTreeModel<Domain::Task::Ptr, TaskExtraDataPtr>(query, flags, data, setData, drop, drag, fetchAdditionalInfo, this);
0160 }
0161 
0162 #include "moc_contextpagemodel.cpp"