File indexing completed on 2024-11-17 04:55:41

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 "KNSReviews.h"
0008 #include "KNSBackend.h"
0009 #include "KNSResource.h"
0010 #include <KLocalizedString>
0011 #include <KNSCore/EngineBase>
0012 #include <KPasswordDialog>
0013 #include <QDebug>
0014 #include <QDesktopServices>
0015 #include <ReviewsBackend/Rating.h>
0016 #include <ReviewsBackend/Review.h>
0017 #include <attica/content.h>
0018 #include <attica/providermanager.h>
0019 #include <resources/AbstractResource.h>
0020 
0021 KNSReviews::KNSReviews(KNSBackend *backend)
0022     : AbstractReviewsBackend(backend)
0023     , m_backend(backend)
0024 {
0025 }
0026 
0027 Rating *KNSReviews::ratingForApplication(AbstractResource *resource) const
0028 {
0029     KNSResource *knsResource = qobject_cast<KNSResource *>(resource);
0030     if (!knsResource) {
0031         qDebug() << resource->packageName() << "<= couldn't find resource";
0032         return nullptr;
0033     }
0034 
0035     return knsResource->ratingInstance();
0036 }
0037 
0038 void KNSReviews::fetchReviews(AbstractResource *resource, int page)
0039 {
0040     const auto job = provider().requestComments(Attica::Comment::ContentComment, resource->packageName(), QStringLiteral("0"), page - 1, 10);
0041     if (!job) {
0042         Q_EMIT reviewsReady(resource, {}, false);
0043         return;
0044     }
0045     job->setProperty("app", QVariant::fromValue(resource));
0046     connect(job, &Attica::BaseJob::finished, this, &KNSReviews::commentsReceived);
0047     job->start();
0048     acquireFetching(true);
0049 }
0050 
0051 void KNSReviews::acquireFetching(bool fetching)
0052 {
0053     if (fetching) {
0054         m_fetching++;
0055     } else {
0056         m_fetching--;
0057     }
0058 
0059     if ((!fetching && m_fetching == 0) || (fetching && m_fetching == 1)) {
0060         Q_EMIT fetchingChanged(m_fetching != 0);
0061     }
0062     Q_ASSERT(m_fetching >= 0);
0063 }
0064 
0065 static QVector<ReviewPtr> createReviewList(AbstractResource *resource, const Attica::Comment::List comments, int depth = 0)
0066 {
0067     QVector<ReviewPtr> reviews;
0068     for (const Attica::Comment &comment : comments) {
0069         // TODO: language lookup?
0070         ReviewPtr r(new Review(resource->name(),
0071                                resource->packageName(),
0072                                QStringLiteral("en"),
0073                                comment.subject(),
0074                                comment.text(),
0075                                comment.user(),
0076                                comment.date(),
0077                                true,
0078                                comment.id().toInt(),
0079                                comment.score() / 10,
0080                                0,
0081                                0,
0082                                0.0,
0083                                QString()));
0084         r->addMetadata(QStringLiteral("NumberOfParents"), depth);
0085         reviews += r;
0086         if (comment.childCount() > 0) {
0087             reviews += createReviewList(resource, comment.children(), depth + 1);
0088         }
0089     }
0090     return reviews;
0091 }
0092 
0093 void KNSReviews::commentsReceived(Attica::BaseJob *j)
0094 {
0095     acquireFetching(false);
0096     const auto job = static_cast<Attica::ListJob<Attica::Comment> *>(j);
0097 
0098     const auto app = job->property("app").value<AbstractResource *>();
0099     QVector<ReviewPtr> reviews = createReviewList(app, job->itemList());
0100 
0101     Q_EMIT reviewsReady(app, reviews, !reviews.isEmpty());
0102 }
0103 
0104 bool KNSReviews::isFetching() const
0105 {
0106     return m_fetching > 0;
0107 }
0108 
0109 void KNSReviews::flagReview(Review * /*r*/, const QString & /*reason*/, const QString & /*text*/)
0110 {
0111     qWarning() << "cannot flag reviews";
0112 }
0113 
0114 void KNSReviews::deleteReview(Review * /*r*/)
0115 {
0116     qWarning() << "cannot delete comments";
0117 }
0118 
0119 void KNSReviews::sendReview(AbstractResource *resource, const QString &summary, const QString &reviewText, const QString &rating, const QString &userName)
0120 {
0121     Q_UNUSED(userName);
0122     provider().voteForContent(resource->packageName(), rating.toUInt() * 20);
0123     if (!summary.isEmpty()) {
0124         provider().addNewComment(Attica::Comment::ContentComment, resource->packageName(), QString(), QString(), summary, reviewText);
0125     }
0126 }
0127 
0128 void KNSReviews::submitUsefulness(Review *review, bool useful)
0129 {
0130     provider().voteForComment(QString::number(review->id()), useful * 5);
0131 }
0132 
0133 void KNSReviews::logout()
0134 {
0135     bool ok = provider().saveCredentials(QString(), QString());
0136     if (!ok) {
0137         qWarning() << "couldn't log out";
0138     }
0139 }
0140 
0141 void KNSReviews::registerAndLogin()
0142 {
0143     QDesktopServices::openUrl(provider().baseUrl());
0144 }
0145 
0146 void KNSReviews::login()
0147 {
0148     const auto dialog = new KPasswordDialog;
0149     dialog->setPrompt(i18n("Log in information for %1", provider().name()));
0150     connect(dialog, &KPasswordDialog::gotUsernameAndPassword, this, &KNSReviews::credentialsReceived);
0151 }
0152 
0153 void KNSReviews::credentialsReceived(const QString &user, const QString &password)
0154 {
0155     bool ok = provider().saveCredentials(user, password);
0156     if (!ok) {
0157         qWarning() << "couldn't save" << user << "credentials for" << provider().name();
0158     }
0159 }
0160 
0161 bool KNSReviews::hasCredentials() const
0162 {
0163     return provider().hasCredentials();
0164 }
0165 
0166 QString KNSReviews::userName() const
0167 {
0168     QString user, password;
0169     provider().loadCredentials(user, password);
0170     return user;
0171 }
0172 
0173 Attica::Provider KNSReviews::provider() const
0174 {
0175     if (m_backend->engine()->atticaProviders().isEmpty()) {
0176         return {};
0177     }
0178     return *m_backend->engine()->atticaProviders().constFirst();
0179 }
0180 
0181 bool KNSReviews::isResourceSupported(AbstractResource *resource) const
0182 {
0183     return qobject_cast<KNSResource *>(resource);
0184 }