File indexing completed on 2025-02-02 05:02:39
0001 /* 0002 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "tripgroupproxymodel.h" 0008 #include "timelinemodel.h" 0009 #include "tripgroup.h" 0010 #include "tripgroupmanager.h" 0011 0012 #include <QDebug> 0013 #include <QSettings> 0014 0015 TripGroupProxyModel::TripGroupProxyModel(QObject *parent) 0016 : QSortFilterProxyModel(parent) 0017 { 0018 QSettings settings; 0019 settings.beginGroup(QLatin1StringView("TripGroupProxyState")); 0020 for (const auto &key : settings.childKeys()) { 0021 m_collapsed[key] = settings.value(key).toBool(); 0022 } 0023 } 0024 0025 TripGroupProxyModel::~TripGroupProxyModel() = default; 0026 0027 void TripGroupProxyModel::setSourceModel(QAbstractItemModel *sourceModel) 0028 { 0029 m_sourceModel = qobject_cast<TimelineModel*>(sourceModel); 0030 Q_ASSERT(m_sourceModel); 0031 connect(m_sourceModel, &TimelineModel::todayRowChanged, this, &TripGroupProxyModel::todayRowChanged); 0032 connect(m_sourceModel, &TimelineModel::todayRowChanged, this, &TripGroupProxyModel::invalidateFilter); 0033 QSortFilterProxyModel::setSourceModel(m_sourceModel); 0034 } 0035 0036 QVariant TripGroupProxyModel::data(const QModelIndex &index, int role) const 0037 { 0038 if (role == TimelineModel::ElementRangeRole) { 0039 const auto srcIdx = mapToSource(index); 0040 const auto elementType = srcIdx.data(TimelineModel::ElementTypeRole).toInt(); 0041 const auto rangeType = srcIdx.data(TimelineModel::ElementRangeRole).toInt(); 0042 if (elementType == TimelineElement::TripGroup && rangeType == TimelineElement::RangeBegin) { 0043 const auto groupId = srcIdx.data(TimelineModel::TripGroupIdRole).toString(); 0044 if (isCollapsed(groupId)) { 0045 return TimelineElement::SelfContained; 0046 } 0047 } 0048 } 0049 return QSortFilterProxyModel::data(index, role); 0050 } 0051 0052 bool TripGroupProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const 0053 { 0054 // ### we can probably do this more efficiently! 0055 for (int i = source_row; i < m_sourceModel->rowCount(); ++i) { 0056 const auto srcIdx = m_sourceModel->index(i, 0); 0057 const auto elementType = srcIdx.data(TimelineModel::ElementTypeRole).toInt(); 0058 const auto rangeType = srcIdx.data(TimelineModel::ElementRangeRole).toInt(); 0059 if (elementType == TimelineElement::TripGroup && rangeType == TimelineElement::RangeBegin) { 0060 // either this is our group's start, or a group after us 0061 return true; 0062 } 0063 if (elementType != TimelineElement::TripGroup) { 0064 continue; 0065 } 0066 const auto groupId = srcIdx.data(TimelineModel::TripGroupIdRole).toString(); 0067 return !isCollapsed(groupId); 0068 } 0069 0070 return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); 0071 } 0072 0073 int TripGroupProxyModel::todayRow() 0074 { 0075 const auto srcIdx = m_sourceModel->index(m_sourceModel->todayRow(), 0); 0076 return mapFromSource(srcIdx).row(); 0077 } 0078 0079 void TripGroupProxyModel::collapse(const QString &groupId) 0080 { 0081 m_collapsed[groupId] = true; 0082 invalidateFilter(); 0083 0084 const auto startSrcIdx = m_sourceModel->match(m_sourceModel->index(0, 0), TimelineModel::TripGroupIdRole, groupId, 1, Qt::MatchExactly).at(0); 0085 Q_ASSERT(startSrcIdx.isValid()); 0086 const auto startIdx = mapFromSource(startSrcIdx); 0087 Q_EMIT dataChanged(startIdx, startIdx); // collapse/expand state changed 0088 0089 QSettings settings; 0090 settings.beginGroup(QLatin1StringView("TripGroupProxyState")); 0091 settings.setValue(groupId, true); 0092 } 0093 0094 void TripGroupProxyModel::expand(const QString &groupId) 0095 { 0096 m_collapsed[groupId] = false; 0097 invalidateFilter(); 0098 0099 const auto startSrcIdx = m_sourceModel->match(m_sourceModel->index(0, 0), TimelineModel::TripGroupIdRole, groupId, 1, Qt::MatchExactly).at(0); 0100 Q_ASSERT(startSrcIdx.isValid()); 0101 const auto startIdx = mapFromSource(startSrcIdx); 0102 Q_EMIT dataChanged(startIdx, startIdx); // collapse/expand state changed 0103 0104 QSettings settings; 0105 settings.beginGroup(QLatin1StringView("TripGroupProxyState")); 0106 settings.setValue(groupId, false); 0107 } 0108 0109 bool TripGroupProxyModel::isCollapsed(const QString &groupId) const 0110 { 0111 const auto g = m_sourceModel->tripGroupManager()->tripGroup(groupId); 0112 const auto now = m_sourceModel->now(); 0113 if (g.beginDateTime() <= now && now <= g.endDateTime()) { 0114 return false; // the current trip must always be expanded 0115 } 0116 0117 const auto it = m_collapsed.constFind(groupId); 0118 if (it != m_collapsed.constEnd()) { 0119 return it.value(); 0120 } 0121 0122 // by default collapse past trips 0123 return g.endDateTime() < now; 0124 } 0125 0126 #include "moc_tripgroupproxymodel.cpp"