Skip to content
Snippets Groups Projects
serviceconnector.cpp 4.68 KiB
/****************************************************************************
**
** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Viewer of the Qt Toolkit.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/

#include "serviceconnector.h"

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QJsonDocument>
#include <QJsonObject>

std::optional<QByteArray> ServiceConnector::fetchResource(const QString &url, const QString &auth)
{
    qDebug() << "Fetching resource from" << url;

    QNetworkRequest request(url);
    request.setRawHeader("Authorization", auth.toUtf8());
    QSharedPointer<QNetworkReply> reply(m_manager.get(request));
    QObject::connect(reply.data(),
                     &QNetworkReply::sslErrors,
                     this,
                     [&](const QList<QSslError> &errors) {
                         qWarning() << errors.first().errorString();
                     });

    QEventLoop loop;
    QObject::connect(this, &ServiceConnector::interrupted, reply.data(), [&]() {
        qDebug() << "Aborting network request";
        reply->abort();
        loop.quit();
    });
    QObject::connect(reply.data(), &QNetworkReply::finished, &loop, &QEventLoop::quit);
    QObject::connect(reply.data(),
                     &QNetworkReply::downloadProgress,
                     this,
                     [&](qint64 bytesReceived, qint64 bytesTotal) {
                         float percentage = roundf((float) bytesReceived / (float) bytesTotal * 100);
                         qDebug() << "Download progress" << QString::number(percentage) << "% -"
                                  << QString::number(bytesReceived) << "/"
                                  << QString::number(bytesTotal);
                         emit downloadProgress(percentage);
                     });
    loop.exec();

    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << reply->errorString();
        return {};
    }

    qDebug() << "Resource fetched successfully";
    return reply->readAll();
}

std::optional<QByteArray> ServiceConnector::fetchProject(const QString &url)
{
    QString projectUrl = url;
    if (projectUrl.startsWith(m_serviceUrl + "/#")) {
        projectUrl = projectUrl.split("#").at(1);
        projectUrl.prepend(m_serviceUrl + "/qmlprojects/");
    }

    return fetchResource(projectUrl);
}

std::optional<QByteArray> ServiceConnector::fetchUserProject(const QString &userHash,
                                                             const QString &projectName,
                                                             const QString &password)
{
    const QString projectUrl = m_serviceUrl + "/qmlprojects/" + userHash + "/" + projectName
                               + ".qmlrc";

    return fetchResource(projectUrl, password);
}

std::optional<QJsonArray> ServiceConnector::fetchUserProjectList(const QString &userHash)
{
    auto reply = fetchResource(m_serviceUrl + "/api/v1/qmlrc/list/" + userHash + "?key=818815");

    if (!reply)
        return {};

    QJsonArray projectList = QJsonDocument::fromJson(reply.value())
                                 .object()
                                 .value("data")
                                 .toObject()
                                 .value("packages")
                                 .toArray();

    return projectList;
}

std::optional<QJsonArray> ServiceConnector::fetchDemoList()
{
    auto reply = fetchResource(m_serviceUrl + "/api/v1/demos");
    if (!reply)
        return {};

    return QJsonDocument::fromJson(reply.value()).array();
}

std::optional<QByteArray> ServiceConnector::fetchDemo(const QString &demoName)
{
    return fetchResource(m_serviceUrl + "/qmlprojects/demos/" + demoName + ".qmlrc");
}