File indexing completed on 2024-05-12 05:36:51

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 #include "ProcessSortFilterModel.h"
0008 
0009 #include <QDebug>
0010 
0011 #include <processcore/process_data_model.h>
0012 
0013 using namespace KSysGuard;
0014 
0015 ProcessSortFilterModel::ProcessSortFilterModel(QObject *parent)
0016     : QSortFilterProxyModel(parent)
0017 {
0018     setSortRole(ProcessDataModel::Value);
0019     setSortCaseSensitivity(Qt::CaseInsensitive);
0020     setSortLocaleAware(true);
0021 
0022     setFilterRole(ProcessDataModel::Value);
0023     setFilterCaseSensitivity(Qt::CaseInsensitive);
0024     setRecursiveFilteringEnabled(true);
0025     setAutoAcceptChildRows(true);
0026 }
0027 
0028 void ProcessSortFilterModel::setSourceModel(QAbstractItemModel *newSourceModel)
0029 {
0030     auto oldSourceModel = sourceModel();
0031 
0032     if (newSourceModel == oldSourceModel) {
0033         return;
0034     }
0035 
0036     if (oldSourceModel) {
0037         oldSourceModel->disconnect(this);
0038     }
0039 
0040     QSortFilterProxyModel::setSourceModel(newSourceModel);
0041     if (newSourceModel) {
0042         connect(newSourceModel, &QAbstractItemModel::modelReset, this, &ProcessSortFilterModel::findColumns);
0043         connect(newSourceModel, &QAbstractItemModel::columnsInserted, this, &ProcessSortFilterModel::findColumns);
0044         connect(newSourceModel, &QAbstractItemModel::columnsRemoved, this, &ProcessSortFilterModel::findColumns);
0045         connect(newSourceModel, &QAbstractItemModel::columnsMoved, this, &ProcessSortFilterModel::findColumns);
0046         findColumns();
0047     }
0048 }
0049 
0050 bool ProcessSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0051 {
0052     // not handled a reset yet, we'll invalidate at the end of modelReset anyway
0053     if (m_uidColumn == -1 && m_pidColumn == -1 && filterKeyColumn() == -1) {
0054         return false;
0055     }
0056 
0057     auto source = sourceModel();
0058 
0059     bool result = true;
0060 
0061     if (m_viewMode != ViewAll && m_uidColumn != -1) {
0062         auto uid = source->data(source->index(sourceRow, m_uidColumn, sourceParent), ProcessDataModel::Value).toUInt();
0063 
0064         switch (m_viewMode) {
0065         case ViewOwn:
0066             result = m_currentUser.userId().nativeId() == uid;
0067             break;
0068         case ViewUser:
0069             result = uid >= 1000 && uid < 65534;
0070             break;
0071         case ViewSystem:
0072             result = uid < 1000 || uid >= 65534;
0073             break;
0074         default:
0075             break;
0076         }
0077     }
0078 
0079     if (!m_filterPids.isEmpty()) {
0080         auto pid = source->data(source->index(sourceRow, m_pidColumn, sourceParent), ProcessDataModel::Value);
0081         result = m_filterPids.contains(pid);
0082     }
0083 
0084     if (!result) {
0085         return false;
0086     }
0087 
0088     if (filterString().isEmpty()) {
0089         return true;
0090     }
0091 
0092     const QString name = source->data(source->index(sourceRow, 0, sourceParent), filterRole()).toString();
0093 
0094     const QString filter = filterString();
0095     const QList<QStringView> splitFilterStrings = QStringView(filter).split(QLatin1Char(','), Qt::SkipEmptyParts);
0096 
0097     for (const QStringView &string : splitFilterStrings) {
0098         if (name.contains(string.trimmed(), Qt::CaseInsensitive)) {
0099             return true;
0100         }
0101     }
0102 
0103     return false;
0104 }
0105 
0106 bool ProcessSortFilterModel::filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const
0107 {
0108     Q_UNUSED(sourceParent)
0109 
0110     auto attribute = sourceModel()->headerData(sourceColumn, Qt::Horizontal, ProcessDataModel::Attribute).toString();
0111     if (m_hiddenAttributes.contains(attribute)) {
0112         return false;
0113     }
0114 
0115     return true;
0116 }
0117 
0118 QString ProcessSortFilterModel::filterString() const
0119 {
0120     return m_filterString;
0121 }
0122 
0123 void ProcessSortFilterModel::setFilterString(const QString &newFilterString)
0124 {
0125     if (newFilterString == m_filterString) {
0126         return;
0127     }
0128 
0129     m_filterString = newFilterString;
0130     setFilterWildcard(m_filterString);
0131     Q_EMIT filterStringChanged();
0132 }
0133 
0134 ProcessSortFilterModel::ViewMode ProcessSortFilterModel::viewMode() const
0135 {
0136     return m_viewMode;
0137 }
0138 
0139 void ProcessSortFilterModel::setViewMode(ViewMode newViewMode)
0140 {
0141     if (newViewMode == m_viewMode) {
0142         return;
0143     }
0144 
0145     m_viewMode = newViewMode;
0146     invalidateFilter();
0147     Q_EMIT viewModeChanged();
0148 }
0149 
0150 QStringList ProcessSortFilterModel::hiddenAttributes() const
0151 {
0152     return m_hiddenAttributes;
0153 }
0154 
0155 void ProcessSortFilterModel::setHiddenAttributes(const QStringList &newHiddenAttributes)
0156 {
0157     if (newHiddenAttributes == m_hiddenAttributes) {
0158         return;
0159     }
0160 
0161     m_hiddenAttributes = newHiddenAttributes;
0162     invalidateFilter();
0163     Q_EMIT hiddenAttributesChanged();
0164 }
0165 
0166 QVariantList ProcessSortFilterModel::filterPids() const
0167 {
0168     return m_filterPids;
0169 }
0170 
0171 void ProcessSortFilterModel::setFilterPids(const QVariantList &newFilterPids)
0172 {
0173     if (newFilterPids == m_filterPids) {
0174         return;
0175     }
0176 
0177     m_filterPids = newFilterPids;
0178     invalidateFilter();
0179     Q_EMIT filterPidsChanged();
0180 }
0181 
0182 void ProcessSortFilterModel::sort(int column, Qt::SortOrder order)
0183 {
0184     QSortFilterProxyModel::sort(column, order);
0185     Q_EMIT sorted();
0186 }
0187 
0188 void ProcessSortFilterModel::findColumns()
0189 {
0190     m_uidColumn = -1;
0191     m_pidColumn = -1;
0192     int nameColumn = -1;
0193 
0194     auto source = sourceModel();
0195 
0196     for (auto column = 0; column < source->columnCount(); ++column) {
0197         auto attribute = source->headerData(column, Qt::Horizontal, ProcessDataModel::Attribute).toString();
0198         if (attribute == QStringLiteral("uid")) {
0199             m_uidColumn = column;
0200         } else if (attribute == QStringLiteral("pid")) {
0201             m_pidColumn = column;
0202         } else if (attribute == QStringLiteral("name")) {
0203             nameColumn = column;
0204         }
0205     }
0206     setFilterKeyColumn(nameColumn);
0207 }
0208 
0209 #include "moc_ProcessSortFilterModel.cpp"