Six source-code files are below. Apologies for lack of colorization.
apimanager.h - API for the networking stack
appwrapper.h - API for the high-level backend code of the client
apimanager.cpp - Implementation of the networking stack
appwrapper.cpp - Implementation of the high-level backend code of the client
main.cpp - Entry point of the app
Main.qml - GUI, not yet connected to networking stack
//
// apimanager.h
//
#ifndef APIMANAGER_H
#define APIMANAGER_H
#include <memory>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
class APIManager : public QObject
{
Q_OBJECT
public:
explicit APIManager(QObject *parent = nullptr);
~APIManager();
Q_INVOKABLE void getEndpoint();
Q_INVOKABLE void postEndpoint();
QStringList data();
signals:
void dataReadComplete();
private slots:
void dataReadyRead();
void dataRead();
private:
QUrl m_endpoint;
std::unique_ptr<QNetworkAccessManager> m_netManager;
QNetworkReply* m_netReply;
QByteArray m_buffer;
QStringList m_data;
};
#endif // APIMANAGER_H
//
// appwrapper.h
//
#ifndef APP_H
#define APP_H
#include "apimanager.h"
#include <QGuiApplication>
#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlContext>
class AppWrapper : public QObject
{
Q_OBJECT
public:
explicit AppWrapper(QGuiApplication* app);
~AppWrapper();
signals:
private:
QPointer<APIManager> m_APIManager;
QGuiApplication* m_app;
QQmlApplicationEngine m_appEngine;
void resetModel();
};
#endif // APP_H
//
// apimanager.cpp
//
#include "apimanager.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkRequest>
#include <QQmlContext>
#include <QtLogging>
APIManager::APIManager(QObject *parent)
: QObject{parent},
m_netManager(std::make_unique<QNetworkAccessManager>()),
m_endpoint("http://localhost:8080/")
{
}
APIManager::~APIManager()
{
}
void APIManager::getEndpoint()
{
QNetworkRequest request;
request.setUrl(m_endpoint);
m_netReply = m_netManager->get(request);
connect(m_netReply, &QIODevice::readyRead, this, &APIManager::dataReadyRead);
connect(m_netReply, &QNetworkReply::finished, this, &APIManager::dataRead);
}
void APIManager::postEndpoint()
{
}
QStringList APIManager::data()
{
return m_data;
}
void APIManager::dataReadyRead()
{
m_buffer.append(m_netReply->readAll());
}
void APIManager::dataRead()
{
if(m_netReply->error())
{
qWarning() << "Error:" << m_netReply->errorString();
} else
{
QJsonDocument doc = QJsonDocument::fromJson(m_buffer);
QJsonArray array = doc.array();
// Parse the JSON doc and fill m_data with it, if there is data
if(array.size()) {
for(int i = 0; i < array.size(); ++i)
{
QJsonObject object = array.at(i).toObject();
QVariantMap map = object.toVariantMap();
QString key = map["key"].toString();
m_data.append(key);
}
m_buffer.clear();
// Let everyone know we have data
emit dataReadComplete();
}
}
}
//
// appwrapper.cpp
//
#include "appwrapper.h"
#include "apimanager.h"
AppWrapper::AppWrapper(QGuiApplication* app) :
m_app(app)//,
//m_APIManager(new APIManager)
{
m_appEngine.rootContext()->setContextProperty("AppWrapper", this);
//resetModel();
// Set up app engine and QML
connect(
&m_appEngine,
&QQmlApplicationEngine::objectCreationFailed,
m_app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection
);
m_appEngine.loadFromModule("restClient", "Main");
// Reset the QML model after a successful read from the API
//connect(m_APIManager, &APIManager::dataReadComplete, this, &AppWrapper::resetModel);
}
AppWrapper::~AppWrapper()
{
//delete m_APIManager;
}
void AppWrapper::resetModel()
{
m_appEngine.rootContext()->setContextProperty("Data", QVariant::fromValue(m_APIManager->data()));
}
//
// main.cpp
//
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "appwrapper.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
AppWrapper appWrapper(&app);
return app.exec();
}
//
// Main.qml
//
import QtQuick
import QtQuick.Controls.Fusion
import QtQuick.Controls
ApplicationWindow {
id: root
width: 1280
height: 960
visible: true
title: qsTr("CCC Data Ecosystem Tool")
SplitView {
anchors.fill: parent
Pane {
id: sidebar
implicitWidth: parent.width / 6
height: parent.height
Label {
text: "Side Bar"
anchors.centerIn: parent
}
}
Pane {
implicitWidth: parent.width - sidebar.width
height: parent.height
padding: 0
id: mainArea
SplitView {
orientation: Qt.Vertical
anchors.fill: parent
Pane {
id: mainAreaTop
width: parent.width
implicitHeight: parent.height - mainAreaBottom.implicitHeight
TextArea {
anchors.fill: parent
}
}
Pane {
id: mainAreaBottom
width: parent.width
implicitHeight: parent.height / 5
Label {
text: "Main Area Bottom"
anchors.centerIn: parent
}
}
}
}
}
}