Как отобразить объект JSON в QML во вложенном представлении? - PullRequest
0 голосов
/ 09 июля 2019

Я очень плохо знаком с QML.

Я получил некоторый объект JSON из бесплатного веб-API, и теперь у меня есть HackNewsModel, настроенная версия QAbstractListModel.

Заголовочный файл модели.

#ifndef HACKNEWSMODEL_H
#define HACKNEWSMODEL_H

#include "Singleton.hpp"
#include <QAbstractListModel>
#include <QJsonObject>
#include <QDateTime>

struct HackNews
{
    QString m_id;
    bool m_deleted;
    QString m_type;
    QString m_by;
    QDateTime m_time;
    QString m_text;
    bool m_dead;
    QString m_parentId;
    QString m_pollId;
    QStringList m_kidsIdList;
    QString m_url;
    QString m_score;
    QString m_title;
    QStringList m_partsIdList;
    QString m_descendantCount;
};

class HackNewsModel : public QAbstractListModel, public Singleton<HackNewsModel>
{
    Q_OBJECT

public:
    void addHackNews(QJsonObject &hackNews);
    enum Roles {
        Id = Qt::UserRole + 1,
        Deleted,
        Type,
        By,
        Time,
        Text,
        Dead,
        Parent,
        Poll,
        Kids,
        URL,
        Score,
        Title,
        Parts,
        Descendents
    };

    QHash<int, QByteArray> roleNames() const override;

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    QVariant data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const override;

    friend class Singleton<HackNewsModel>;
    explicit HackNewsModel(QObject * parent = nullptr);
    ~HackNewsModel() override;

private:
    QList<HackNews> m_hackNewsList;
    QHash<int, QByteArray> m_roles;

};

#endif // HACKNEWSMODEL_H

Cpp файл.

#include "HackNewsModel.h"
#include <QJsonArray>
#include <QDebug>

HackNewsModel::HackNewsModel(QObject *parent) : QAbstractListModel(parent)
{
    m_roles[Id] = "id";
    m_roles[Deleted] = "deleted";
    m_roles[Type] = "type";
    m_roles[By] = "by";
    m_roles[Time] = "time";
    m_roles[Text] = "text";
    m_roles[Dead] = "dead";
    m_roles[Parent] = "parent";
    m_roles[Poll] = "poll";
    m_roles[Kids] = "kids";
    m_roles[URL] = "url";
    m_roles[Score] = "score";
    m_roles[Title] = "title";
    m_roles[Parts] = "parts";
    m_roles[Descendents] = "descendents";
}

HackNewsModel::~HackNewsModel()
{

}

void HackNewsModel::addHackNews(QJsonObject &hackNews)
{
    QString id = "Demo id";
    bool deleted = false;
    QString type;
    QString by;
    QDateTime time;
    QString text;
    bool dead = false;
    QString parentId;
    QString pollId;
    QStringList kidsIdList;
    QString url;
    QString score;
    QString title;
    QStringList partsIdList;
    QString descendantCount;

    if(hackNews.contains("id"))
    {
        id = hackNews["id"].toVariant().toString();
    }

    if(hackNews.contains("deleted"))
    {
        deleted = hackNews["deleted"].toBool();
    }

    if(hackNews.contains("type"))
    {
        type = hackNews["type"].toString();
    }

    if(hackNews.contains("by"))
    {
        by = hackNews["by"].toString();
    }

    if(hackNews.contains("time"))
    {
        time = QDateTime::fromTime_t(static_cast<unsigned int>(hackNews["time"].toInt()));
    }

    if(hackNews.contains("text"))
    {
        text = hackNews["text"].toString();
    }

    if(hackNews.contains("dead"))
    {
        dead = hackNews["dead"].toBool();
    }

    if(hackNews.contains("parent"))
    {
        parentId = hackNews["parent"].toVariant().toString();
    }

    if(hackNews.contains("poll"))
    {
        pollId = hackNews["poll"].toVariant().toString();
    }

    if(hackNews.contains("kids"))
    {
        foreach (QVariant value, hackNews["kids"].toArray().toVariantList()) {
            kidsIdList.append(value.toString());
        }
    }

    if(hackNews.contains("url"))
    {
        url = hackNews["url"].toString();
    }

    if(hackNews.contains("title"))
    {
        title = hackNews["title"].toString();
    }

    if(hackNews.contains("parts"))
    {
        foreach (QVariant value, hackNews["parts"].toArray().toVariantList()) {
            partsIdList.append(value.toString());
        }
    }

    if(hackNews.contains("descendents"))
    {
        descendantCount = hackNews["descendents"].toVariant().toString();
    }

    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_hackNewsList.append(HackNews{id, deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
    endInsertRows();
}

QHash<int, QByteArray> HackNewsModel::roleNames() const
{
    return m_roles;
}

int HackNewsModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_hackNewsList.size();
}


QVariant HackNewsModel::data(const QModelIndex &index, int role) const
{
    QVariant result;
    if(hasIndex(index.row(), index.column(), index.parent()))
    {
        const HackNews &news = m_hackNewsList.at(index.row());
        switch (role) {
        case Id:
        {
            result = news.m_id;
        }
            break;

        case Deleted:
        {
            result = news.m_deleted;
        }
            break;

        case Type:
        {
            result = news.m_type;
        }
            break;

        case By:
        {
            result = news.m_by;
        }
            break;

        case Time:
        {
            result = news.m_time;
        }
            break;

        case Text:
        {
            result = news.m_text;
        }
            break;

        case Dead:
        {
            result = news.m_dead;
        }
            break;

        case Parent:
        {
            result = news.m_parentId;
        }
            break;

        case Poll:
        {
            result = news.m_pollId;
        }
            break;

        case Kids:
        {
            result = news.m_kidsIdList;
        }
            break;

        case URL:
        {
            result = news.m_url;
        }
            break;

        case Score:
        {
            result = news.m_score;
        }
            break;

        case Title:
        {
            result = news.m_title;
        }
            break;

        case Parts:
        {
            result = news.m_partsIdList;
        }
            break;

        case Descendents:
        {
            result = news.m_descendantCount;
        }
            break;

        default:
            break;
        }
    }

    return result;
}

Я открываю модель для QML в следующем коде.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "NetworkRequestMaker.h"
#include "HackNewsModel.h"
#include <QtWebEngine>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    NetworkRequestMaker testRequestMaker;

    qmlRegisterSingletonType<HackNewsModel>("HackNews", 1, 0, "HackNewsModel",
        [](QQmlEngine *eng, QJSEngine *js) -> QObject *
        {
            eng->setObjectOwnership(&HackNewsModel::getInstance(),
                                   QQmlEngine::ObjectOwnership::CppOwnership);
            return &HackNewsModel::getInstance();
        });


    QtWebEngine::initialize();

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

Возможно ли это с помощью ListView?Как получить доступ к типу QStringList m_kidsIdList в HackNewsModel из QML?

В конечном счете, я хотел бы отобразить содержимое объекта JSON, подобное тому, как оно выглядит на следующем рисунке, как в браузере.

enter image description here

Способна ли созданная мной модель отображению объекта JSON, как показано на рисунке?Можете ли вы посоветовать мне, как правильно его отобразить?

Спасибо.

...