File indexing completed on 2024-05-05 17:33:22

0001 /*
0002  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "libdiscover_debug.h"
0008 #include <ReviewsBackend/AbstractReviewsBackend.h>
0009 #include <ReviewsBackend/Review.h>
0010 #include <resources/AbstractResource.h>
0011 #include <resources/AbstractResourcesBackend.h>
0012 #include <resources/ResourcesModel.h>
0013 
0014 ReviewsModel::ReviewsModel(QObject *parent)
0015     : QAbstractListModel(parent)
0016     , m_lastPage(0)
0017 {
0018 }
0019 
0020 ReviewsModel::~ReviewsModel() = default;
0021 
0022 QHash<int, QByteArray> ReviewsModel::roleNames() const
0023 {
0024     QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
0025     roles.insert(ShouldShow, "shouldShow");
0026     roles.insert(Reviewer, "reviewer");
0027     roles.insert(CreationDate, "date");
0028     roles.insert(UsefulnessTotal, "usefulnessTotal");
0029     roles.insert(UsefulnessFavorable, "usefulnessFavorable");
0030     roles.insert(UsefulChoice, "usefulChoice");
0031     roles.insert(Rating, "rating");
0032     roles.insert(Summary, "summary");
0033     roles.insert(Depth, "depth");
0034     roles.insert(PackageVersion, "packageVersion");
0035     return roles;
0036 }
0037 
0038 QVariant ReviewsModel::data(const QModelIndex &index, int role) const
0039 {
0040     if (!index.isValid())
0041         return QVariant();
0042     switch (role) {
0043     case Qt::DisplayRole:
0044         return m_reviews.at(index.row())->reviewText();
0045     case ShouldShow:
0046         return m_reviews.at(index.row())->shouldShow();
0047     case Reviewer:
0048         return m_reviews.at(index.row())->reviewer();
0049     case CreationDate:
0050         return m_reviews.at(index.row())->creationDate();
0051     case UsefulnessTotal:
0052         return m_reviews.at(index.row())->usefulnessTotal();
0053     case UsefulnessFavorable:
0054         return m_reviews.at(index.row())->usefulnessFavorable();
0055     case UsefulChoice:
0056         return m_reviews.at(index.row())->usefulChoice();
0057     case Rating:
0058         return m_reviews.at(index.row())->rating();
0059     case Summary:
0060         return m_reviews.at(index.row())->summary();
0061     case PackageVersion:
0062         return m_reviews.at(index.row())->packageVersion();
0063     case Depth:
0064         return m_reviews.at(index.row())->getMetadata(QStringLiteral("NumberOfParents")).toInt();
0065     }
0066     return QVariant();
0067 }
0068 
0069 int ReviewsModel::rowCount(const QModelIndex &parent) const
0070 {
0071     if (parent.isValid())
0072         return 0;
0073     return m_reviews.count();
0074 }
0075 
0076 AbstractResource *ReviewsModel::resource() const
0077 {
0078     return m_app;
0079 }
0080 
0081 AbstractReviewsBackend *ReviewsModel::backend() const
0082 {
0083     return m_backend;
0084 }
0085 
0086 void ReviewsModel::setResource(AbstractResource *app)
0087 {
0088     if (m_app != app) {
0089         beginResetModel();
0090         m_reviews.clear();
0091         m_lastPage = 0;
0092 
0093         if (m_backend) {
0094             disconnect(m_backend, &AbstractReviewsBackend::errorMessageChanged, this, &ReviewsModel::restartFetching);
0095             disconnect(m_backend, &AbstractReviewsBackend::reviewsReady, this, &ReviewsModel::addReviews);
0096             disconnect(m_backend, &AbstractReviewsBackend::fetchingChanged, this, &ReviewsModel::fetchingChanged);
0097             disconnect(m_app, &AbstractResource::versionsChanged, this, &ReviewsModel::restartFetching);
0098         }
0099         m_app = app;
0100         m_backend = app ? app->backend()->reviewsBackend() : nullptr;
0101         if (m_backend) {
0102             connect(m_backend, &AbstractReviewsBackend::errorMessageChanged, this, &ReviewsModel::restartFetching);
0103             connect(m_backend, &AbstractReviewsBackend::reviewsReady, this, &ReviewsModel::addReviews);
0104             connect(m_backend, &AbstractReviewsBackend::fetchingChanged, this, &ReviewsModel::fetchingChanged);
0105             connect(m_app, &AbstractResource::versionsChanged, this, &ReviewsModel::restartFetching);
0106 
0107             QMetaObject::invokeMethod(this, &ReviewsModel::restartFetching, Qt::QueuedConnection);
0108         }
0109         endResetModel();
0110         Q_EMIT rowsChanged();
0111         Q_EMIT resourceChanged();
0112     }
0113 }
0114 
0115 void ReviewsModel::restartFetching()
0116 {
0117     if (!m_app || !m_backend)
0118         return;
0119 
0120     m_canFetchMore = true;
0121     m_lastPage = 0;
0122     fetchMore();
0123     Q_EMIT rowsChanged();
0124 }
0125 
0126 void ReviewsModel::fetchMore(const QModelIndex &parent)
0127 {
0128     if (!m_backend || !m_app || parent.isValid() || m_backend->isFetching() || !m_canFetchMore)
0129         return;
0130 
0131     m_lastPage++;
0132     m_backend->fetchReviews(m_app, m_lastPage);
0133     // qCDebug(LIBDISCOVER_LOG) << "fetching reviews... " << m_lastPage;
0134 }
0135 
0136 void ReviewsModel::addReviews(AbstractResource *app, const QVector<ReviewPtr> &reviews, bool canFetchMore)
0137 {
0138     if (app != m_app)
0139         return;
0140 
0141     m_canFetchMore = canFetchMore;
0142     qCDebug(LIBDISCOVER_LOG) << "reviews arrived..." << m_lastPage << reviews.size();
0143 
0144     if (!reviews.isEmpty()) {
0145         beginInsertRows(QModelIndex(), rowCount(), rowCount() + reviews.size() - 1);
0146         m_reviews += reviews;
0147         endInsertRows();
0148         Q_EMIT rowsChanged();
0149     }
0150 }
0151 
0152 bool ReviewsModel::canFetchMore(const QModelIndex & /*parent*/) const
0153 {
0154     return m_canFetchMore;
0155 }
0156 
0157 void ReviewsModel::markUseful(int row, bool useful)
0158 {
0159     Review *r = m_reviews[row].data();
0160     r->setUsefulChoice(useful ? Yes : No);
0161     // qCDebug(LIBDISCOVER_LOG) << "submitting usefulness" << r->applicationName() << r->id() << useful;
0162     m_backend->submitUsefulness(r, useful);
0163     const QModelIndex ind = index(row, 0, QModelIndex());
0164     Q_EMIT dataChanged(ind, ind, {UsefulnessTotal, UsefulnessFavorable, UsefulChoice});
0165 }
0166 
0167 void ReviewsModel::deleteReview(int row)
0168 {
0169     Review *r = m_reviews[row].data();
0170     m_backend->deleteReview(r);
0171 }
0172 
0173 void ReviewsModel::flagReview(int row, const QString &reason, const QString &text)
0174 {
0175     Review *r = m_reviews[row].data();
0176     m_backend->flagReview(r, reason, text);
0177 }
0178 
0179 bool ReviewsModel::isFetching() const
0180 {
0181     return m_backend && m_backend->isFetching();
0182 }
0183 
0184 #include "moc_ReviewsModel.cpp"