File indexing completed on 2024-11-24 05:01:58

0001 /*
0002     SPDX-FileCopyrightText: 2007 Ivan Cukic <ivan.cukic+kde@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "kcategorizeditemsviewmodels_p.h"
0008 #include <KLocalizedString>
0009 #include <QDebug>
0010 
0011 #define COLUMN_COUNT 4
0012 
0013 namespace KCategorizedItemsViewModels
0014 {
0015 // AbstractItem
0016 
0017 QString AbstractItem::name() const
0018 {
0019     return text();
0020 }
0021 
0022 QString AbstractItem::id() const
0023 {
0024     QString plugin = data().toMap()[QStringLiteral("pluginName")].toString();
0025 
0026     if (plugin.isEmpty()) {
0027         return name();
0028     }
0029 
0030     return plugin;
0031 }
0032 
0033 QString AbstractItem::description() const
0034 {
0035     return QLatin1String("");
0036 }
0037 
0038 bool AbstractItem::isFavorite() const
0039 {
0040     return passesFiltering(Filter(QStringLiteral("favorite"), true));
0041 }
0042 
0043 int AbstractItem::running() const
0044 {
0045     return 0;
0046 }
0047 
0048 bool AbstractItem::matches(const QString &pattern) const
0049 {
0050     if (name().contains(pattern, Qt::CaseInsensitive) || description().contains(pattern, Qt::CaseInsensitive)) {
0051         return true;
0052     }
0053     const QStringList itemKeywords = keywords();
0054     return std::any_of(itemKeywords.begin(), itemKeywords.end(), [&pattern](const QString &keyword) {
0055         return keyword.startsWith(pattern, Qt::CaseInsensitive);
0056     });
0057 }
0058 
0059 // DefaultFilterModel
0060 
0061 DefaultFilterModel::DefaultFilterModel(QObject *parent)
0062     : QStandardItemModel(0, 1, parent)
0063 {
0064     setHeaderData(1, Qt::Horizontal, i18n("Filters"));
0065 
0066     connect(this, &QAbstractItemModel::modelReset, this, &DefaultFilterModel::countChanged);
0067     connect(this, &QAbstractItemModel::rowsInserted, this, &DefaultFilterModel::countChanged);
0068     connect(this, &QAbstractItemModel::rowsRemoved, this, &DefaultFilterModel::countChanged);
0069 }
0070 
0071 QHash<int, QByteArray> DefaultFilterModel::roleNames() const
0072 {
0073     static QHash<int, QByteArray> newRoleNames;
0074     if (newRoleNames.isEmpty()) {
0075         newRoleNames = QAbstractItemModel::roleNames();
0076         newRoleNames[FilterTypeRole] = "filterType";
0077         newRoleNames[FilterDataRole] = "filterData";
0078         newRoleNames[SeparatorRole] = "separator";
0079     }
0080     return newRoleNames;
0081 }
0082 
0083 void DefaultFilterModel::addFilter(const QString &caption, const Filter &filter, const QIcon &icon)
0084 {
0085     QList<QStandardItem *> newRow;
0086     QStandardItem *item = new QStandardItem(caption);
0087     item->setData(QVariant::fromValue<Filter>(filter));
0088     if (!icon.isNull()) {
0089         item->setIcon(icon);
0090     }
0091     item->setData(filter.first, FilterTypeRole);
0092     item->setData(filter.second, FilterDataRole);
0093 
0094     newRow << item;
0095     appendRow(newRow);
0096 }
0097 
0098 void DefaultFilterModel::addSeparator(const QString &caption)
0099 {
0100     QList<QStandardItem *> newRow;
0101     QStandardItem *item = new QStandardItem(caption);
0102     item->setEnabled(false);
0103     item->setData(true, SeparatorRole);
0104 
0105     newRow << item;
0106     appendRow(newRow);
0107 }
0108 
0109 QVariantHash DefaultFilterModel::get(int row) const
0110 {
0111     QModelIndex idx = index(row, 0);
0112     QVariantHash hash;
0113 
0114     const QHash<int, QByteArray> roles = roleNames();
0115     for (QHash<int, QByteArray>::const_iterator i = roles.constBegin(); i != roles.constEnd(); ++i) {
0116         hash[i.value()] = data(idx, i.key());
0117     }
0118 
0119     return hash;
0120 }
0121 
0122 // DefaultItemFilterProxyModel
0123 
0124 DefaultItemFilterProxyModel::DefaultItemFilterProxyModel(QObject *parent)
0125     : QSortFilterProxyModel(parent)
0126 {
0127 }
0128 
0129 void DefaultItemFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
0130 {
0131     QStandardItemModel *model = qobject_cast<QStandardItemModel *>(sourceModel);
0132 
0133     if (!model) {
0134         qWarning() << "Expecting a QStandardItemModel!";
0135         return;
0136     }
0137 
0138     QSortFilterProxyModel::setSourceModel(model);
0139     connect(this, &QAbstractItemModel::modelReset, this, &DefaultItemFilterProxyModel::countChanged);
0140     connect(this, &QAbstractItemModel::rowsInserted, this, &DefaultItemFilterProxyModel::countChanged);
0141     connect(this, &QAbstractItemModel::rowsRemoved, this, &DefaultItemFilterProxyModel::countChanged);
0142 }
0143 
0144 QAbstractItemModel *DefaultItemFilterProxyModel::sourceModel() const
0145 {
0146     return QSortFilterProxyModel::sourceModel();
0147 }
0148 
0149 int DefaultItemFilterProxyModel::columnCount(const QModelIndex &index) const
0150 {
0151     Q_UNUSED(index);
0152     return COLUMN_COUNT;
0153 }
0154 
0155 QVariant DefaultItemFilterProxyModel::data(const QModelIndex &index, int role) const
0156 {
0157     return QSortFilterProxyModel::data(index, role);
0158 }
0159 
0160 bool DefaultItemFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0161 {
0162     QStandardItemModel *model = (QStandardItemModel *)sourceModel();
0163 
0164     QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
0165 
0166     AbstractItem *item = (AbstractItem *)model->itemFromIndex(index);
0167     // qDebug() << "ITEM " << (item ? "IS NOT " : "IS") << " NULL\n";
0168 
0169     return item && (m_filter.first.isEmpty() || item->passesFiltering(m_filter)) && (m_searchPattern.isEmpty() || item->matches(m_searchPattern));
0170 }
0171 
0172 QVariantHash DefaultItemFilterProxyModel::get(int row) const
0173 {
0174     QModelIndex idx = index(row, 0);
0175     QVariantHash hash;
0176 
0177     const QHash<int, QByteArray> roles = roleNames();
0178     for (QHash<int, QByteArray>::const_iterator i = roles.constBegin(); i != roles.constEnd(); ++i) {
0179         hash[i.value()] = data(idx, i.key());
0180     }
0181 
0182     return hash;
0183 }
0184 
0185 bool DefaultItemFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
0186 {
0187     return sourceModel()->data(left).toString().localeAwareCompare(sourceModel()->data(right).toString()) < 0;
0188 }
0189 
0190 void DefaultItemFilterProxyModel::setSearchTerm(const QString &pattern)
0191 {
0192     m_searchPattern = pattern;
0193     invalidateFilter();
0194     Q_EMIT searchTermChanged(pattern);
0195 }
0196 
0197 QString DefaultItemFilterProxyModel::searchTerm() const
0198 {
0199     return m_searchPattern;
0200 }
0201 
0202 void DefaultItemFilterProxyModel::setFilter(const Filter &filter)
0203 {
0204     m_filter = filter;
0205     invalidateFilter();
0206     Q_EMIT filterChanged();
0207 }
0208 
0209 void DefaultItemFilterProxyModel::setFilterType(const QString &type)
0210 {
0211     m_filter.first = type;
0212     invalidateFilter();
0213     Q_EMIT filterChanged();
0214 }
0215 
0216 QString DefaultItemFilterProxyModel::filterType() const
0217 {
0218     return m_filter.first;
0219 }
0220 
0221 void DefaultItemFilterProxyModel::setFilterQuery(const QVariant &query)
0222 {
0223     m_filter.second = query;
0224     invalidateFilter();
0225     Q_EMIT filterChanged();
0226 }
0227 
0228 QVariant DefaultItemFilterProxyModel::filterQuery() const
0229 {
0230     return m_filter.second;
0231 }
0232 
0233 }