File indexing completed on 2024-05-12 05:29:04

0001 /*
0002  *   SPDX-FileCopyrightText: 2010 Jonathan Thomas <echidnaman@kubuntu.org>
0003  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0004  *
0005  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006  */
0007 
0008 #pragma once
0009 
0010 #include <QQmlParserStatus>
0011 #include <QSortFilterProxyModel>
0012 #include <QString>
0013 #include <QStringList>
0014 #include <QTimer>
0015 
0016 #include <Category/Category.h>
0017 
0018 #include "AbstractResource.h"
0019 #include "AbstractResourcesBackend.h"
0020 #include "discovercommon_export.h"
0021 
0022 class AggregatedResultsStream;
0023 
0024 /*
0025  * This class encapsulates model's counter. The string property is a
0026  * pre-formatted number possibly with extra symbols for a "rough" appearance.
0027  * If counter is not valid, accessing its number and string is pointless.
0028  */
0029 class DISCOVERCOMMON_EXPORT ResourcesCount
0030 {
0031     Q_GADGET
0032     Q_PROPERTY(bool valid MEMBER m_valid CONSTANT FINAL)
0033     Q_PROPERTY(int number MEMBER m_number CONSTANT FINAL)
0034     Q_PROPERTY(QString string MEMBER m_string CONSTANT FINAL)
0035 
0036 public:
0037     explicit ResourcesCount();
0038     explicit ResourcesCount(int number);
0039     explicit ResourcesCount(int number, const QString &string);
0040 
0041 private:
0042     bool m_valid;
0043     int m_number;
0044     QString m_string;
0045 };
0046 
0047 class DISCOVERCOMMON_EXPORT ResourcesProxyModel : public QAbstractListModel, public QQmlParserStatus
0048 {
0049     Q_OBJECT
0050     Q_INTERFACES(QQmlParserStatus)
0051     Q_PROPERTY(Roles sortRole READ sortRole WRITE setSortRole NOTIFY sortRoleChanged)
0052     Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
0053     Q_PROPERTY(Category *filteredCategory READ filteredCategory WRITE setFiltersFromCategory NOTIFY categoryChanged)
0054     Q_PROPERTY(QString filteredCategoryName READ filteredCategoryName WRITE setFilteredCategoryName NOTIFY categoryChanged)
0055     Q_PROPERTY(QString originFilter READ originFilter WRITE setOriginFilter)
0056     Q_PROPERTY(AbstractResource::State stateFilter READ stateFilter WRITE setStateFilter NOTIFY stateFilterChanged)
0057     Q_PROPERTY(bool filterMinimumState READ filterMinimumState WRITE setFilterMinimumState NOTIFY filterMinimumStateChanged)
0058     Q_PROPERTY(QString mimeTypeFilter READ mimeTypeFilter WRITE setMimeTypeFilter)
0059     Q_PROPERTY(AbstractResourcesBackend *backendFilter READ backendFilter WRITE setBackendFilter)
0060     Q_PROPERTY(QString search READ lastSearch WRITE setSearch NOTIFY searchChanged)
0061     Q_PROPERTY(QUrl resourcesUrl READ resourcesUrl WRITE setResourcesUrl NOTIFY resourcesUrlChanged)
0062     Q_PROPERTY(QString extending READ extends WRITE setExtends)
0063     Q_PROPERTY(bool allBackends READ allBackends WRITE setAllBackends)
0064     Q_PROPERTY(QVariantList subcategories READ subcategories NOTIFY subcategoriesChanged)
0065     Q_PROPERTY(bool busy READ isBusy NOTIFY busyChanged)
0066     Q_PROPERTY(ResourcesCount count READ count NOTIFY countChanged FINAL)
0067 public:
0068     explicit ResourcesProxyModel(QObject *parent = nullptr);
0069     // Make sure the role values don't change since some get stored in config files.
0070     enum Roles {
0071         NameRole = Qt::UserRole,
0072         IconRole,
0073         CommentRole,
0074         StateRole,
0075         RatingRole,
0076         RatingPointsRole,
0077         RatingCountRole,
0078         SortableRatingRole,
0079         InstalledRole,
0080         ApplicationRole,
0081         OriginRole,
0082         DisplayOriginRole,
0083         CanUpgrade,
0084         PackageNameRole,
0085         CategoryRole,
0086         SectionRole,
0087         MimeTypes,
0088         SizeRole,
0089         LongDescriptionRole,
0090         SourceIconRole,
0091         ReleaseDateRole,
0092         // This is better that's always the last value as this one should be never saved to disk
0093         SearchRelevanceRole
0094     };
0095     Q_ENUM(Roles)
0096 
0097     QHash<int, QByteArray> roleNames() const override;
0098 
0099     void setSearch(const QString &text);
0100     QString lastSearch() const;
0101     void setOriginFilter(const QString &origin);
0102     QString originFilter() const;
0103     void setFiltersFromCategory(Category *category);
0104     void setStateFilter(AbstractResource::State s);
0105     AbstractResource::State stateFilter() const;
0106     void setSortRole(Roles sortRole);
0107     Roles sortRole() const
0108     {
0109         return m_sortRole;
0110     }
0111     void setSortOrder(Qt::SortOrder sortOrder);
0112     Qt::SortOrder sortOrder() const
0113     {
0114         return m_sortOrder;
0115     }
0116     void setFilterMinimumState(bool filterMinimumState);
0117     bool filterMinimumState() const;
0118 
0119     Category *filteredCategory() const;
0120     QString filteredCategoryName() const;
0121     void setFilteredCategoryName(const QString &cat);
0122 
0123     QString mimeTypeFilter() const;
0124     void setMimeTypeFilter(const QString &mime);
0125 
0126     QString extends() const;
0127     void setExtends(const QString &extends);
0128 
0129     QUrl resourcesUrl() const;
0130     void setResourcesUrl(const QUrl &resourcesUrl);
0131 
0132     bool allBackends() const;
0133     void setAllBackends(bool allBackends);
0134 
0135     AbstractResourcesBackend *backendFilter() const;
0136     void setBackendFilter(AbstractResourcesBackend *filtered);
0137 
0138     QVariantList subcategories() const;
0139 
0140     QVariant data(const QModelIndex &index, int role) const override;
0141     int rowCount(const QModelIndex &parent = {}) const override;
0142 
0143     Q_SCRIPTABLE int indexOf(AbstractResource *res);
0144     Q_SCRIPTABLE AbstractResource *resourceAt(int row) const;
0145 
0146     bool isBusy() const
0147     {
0148         return m_currentStream != nullptr;
0149     }
0150 
0151     bool orderedLessThan(const StreamResult &left, const StreamResult &right) const;
0152     Q_SCRIPTABLE void invalidateFilter();
0153     void invalidateSorting();
0154 
0155     bool canFetchMore(const QModelIndex &parent) const override;
0156     void fetchMore(const QModelIndex &parent) override;
0157 
0158     void classBegin() override
0159     {
0160     }
0161     void componentComplete() override;
0162 
0163     ResourcesCount count() const;
0164 
0165 private Q_SLOTS:
0166     void refreshBackend(AbstractResourcesBackend *backend, const QVector<QByteArray> &properties);
0167     void refreshResource(AbstractResource *resource, const QVector<QByteArray> &properties);
0168     void removeResource(AbstractResource *resource);
0169 
0170 private:
0171     void sortedInsertion(const QVector<StreamResult> &res);
0172     QVariant roleToValue(const StreamResult &result, int role) const;
0173     QVariant roleToOrderedValue(const StreamResult &result, int role) const;
0174 
0175     QVector<int> propertiesToRoles(const QVector<QByteArray> &properties) const;
0176     void addResources(const QVector<StreamResult> &res);
0177     void fetchSubcategories();
0178     void removeDuplicates(QVector<StreamResult> &newResources);
0179     bool isSorted(const QVector<StreamResult> &resources);
0180 
0181     Roles m_sortRole;
0182     Qt::SortOrder m_sortOrder;
0183 
0184     bool m_setup = false;
0185     QString m_categoryName;
0186 
0187     AbstractResourcesBackend::Filters m_filters;
0188     QVariantList m_subcategories;
0189 
0190     QVector<StreamResult> m_displayedResources;
0191     static const QHash<int, QByteArray> s_roles;
0192     ResultsStream *m_currentStream;
0193     QTimer m_countTimer;
0194 
0195 Q_SIGNALS:
0196     void busyChanged();
0197     void sortRoleChanged(int sortRole);
0198     void sortOrderChanged(Qt::SortOrder order);
0199     void categoryChanged();
0200     void stateFilterChanged();
0201     void searchChanged(const QString &search);
0202     void subcategoriesChanged(const QVariantList &subcategories);
0203     void resourcesUrlChanged(const QUrl &url);
0204     void countChanged();
0205     void filterMinimumStateChanged(bool filterMinimumState);
0206 };