File indexing completed on 2025-01-05 04:59:44

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0003  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004  */
0005 
0006 #include <QRegularExpression>
0007 
0008 #include "taskfilterproxymodel.h"
0009 
0010 #include <limits>
0011 
0012 #include "domain/task.h"
0013 #include "utils/datetime.h"
0014 
0015 #include "presentation/querytreemodelbase.h"
0016 
0017 using namespace Presentation;
0018 
0019 TaskFilterProxyModel::TaskFilterProxyModel(QObject *parent)
0020     : QSortFilterProxyModel(parent),
0021       m_sortType(TitleSort),
0022       m_showDone(false),
0023       m_showFuture(false)
0024 {
0025     setDynamicSortFilter(true);
0026     setSortCaseSensitivity(Qt::CaseInsensitive);
0027     setSortOrder(Qt::AscendingOrder);
0028 }
0029 
0030 TaskFilterProxyModel::SortType TaskFilterProxyModel::sortType() const
0031 {
0032     return m_sortType;
0033 }
0034 
0035 void TaskFilterProxyModel::setSortType(TaskFilterProxyModel::SortType type)
0036 {
0037     m_sortType = type;
0038     invalidate();
0039 }
0040 
0041 void TaskFilterProxyModel::setSortOrder(Qt::SortOrder order)
0042 {
0043     sort(0, order);
0044 }
0045 
0046 bool TaskFilterProxyModel::showDoneTasks() const
0047 {
0048     return m_showDone;
0049 }
0050 
0051 void TaskFilterProxyModel::setShowDoneTasks(bool show)
0052 {
0053     if (m_showDone == show)
0054         return;
0055 
0056     m_showDone = show;
0057     invalidate();
0058 }
0059 
0060 static bool isDoneTask(const Domain::Task::Ptr &task)
0061 {
0062     if (!task)
0063         return false;
0064 
0065     return task->isDone();
0066 }
0067 
0068 bool TaskFilterProxyModel::showFutureTasks() const
0069 {
0070     return m_showFuture;
0071 }
0072 
0073 void TaskFilterProxyModel::setShowFutureTasks(bool show)
0074 {
0075     if (m_showFuture == show)
0076         return;
0077 
0078     m_showFuture = show;
0079     invalidate();
0080 }
0081 
0082 static bool isFutureTask(const Domain::Task::Ptr &task)
0083 {
0084     if (!task)
0085         return false;
0086 
0087     if (!task->startDate().isValid())
0088         return false;
0089 
0090     return task->startDate() > Utils::DateTime::currentDate();
0091 }
0092 
0093 bool TaskFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0094 {
0095     const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
0096     const auto task = index.data(QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>();
0097     if (task) {
0098         QRegularExpression regexp = filterRegularExpression();
0099         regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
0100 
0101         if (task->title().contains(regexp)
0102          || task->text().contains(regexp)) {
0103             return (m_showDone || !isDoneTask(task)) && (m_showFuture || !isFutureTask(task));
0104         }
0105     }
0106 
0107     for (int childRow = 0; childRow < sourceModel()->rowCount(index); childRow++) {
0108         if (filterAcceptsRow(childRow, index))
0109             return true;
0110     }
0111 
0112     return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
0113 }
0114 
0115 static QDate validDate(const QDate &date = QDate())
0116 {
0117     if (date.isValid())
0118         return date;
0119 
0120     return QDate(80000, 12, 31);
0121 }
0122 
0123 bool TaskFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
0124 {
0125     if (m_sortType != DateSort)
0126         return QSortFilterProxyModel::lessThan(left, right);
0127 
0128     const auto leftTask = left.data(QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>();
0129     const auto rightTask = right.data(QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>();
0130 
0131     // The addDays(1) is so that we sort non-tasks (e.g. notes) at the end
0132 
0133     const QDate leftDue = leftTask ? validDate(leftTask->dueDate()) : validDate().addDays(1);
0134     const QDate rightDue = rightTask ? validDate(rightTask->dueDate()) : validDate().addDays(1);
0135 
0136     const QDate leftStart = leftTask ? validDate(leftTask->startDate()) : validDate().addDays(1);
0137     const QDate rightStart = rightTask ? validDate(rightTask->startDate()) : validDate().addDays(1);
0138 
0139     return leftDue < rightDue
0140         || leftStart < rightStart;
0141 }
0142 
0143 #include "moc_taskfilterproxymodel.cpp"