1
0
Fork 0

FGQCanvas: load config on start mode

This commit is contained in:
James Turner 2018-06-24 14:11:38 +01:00
parent 57fbd2fe01
commit b0aa3b93b7
19 changed files with 181 additions and 29 deletions

View file

@ -55,6 +55,8 @@ set(SOURCES
canvasdisplay.h
canvaspainteddisplay.cpp
canvaspainteddisplay.h
jsonutils.cpp
jsonutils.h
)
qt5_add_resources(qrc_sources fgqcanvas_resources.qrc)

View file

@ -32,7 +32,9 @@
#include <QFileInfo>
#include <QRegularExpression>
#include <QDataStream>
#include <QWindow>
#include "jsonutils.h"
#include "canvasconnection.h"
ApplicationController::ApplicationController(QObject *parent)
@ -57,6 +59,26 @@ ApplicationController::~ApplicationController()
delete m_netAccess;
}
void ApplicationController::setWindow(QWindow *window)
{
m_window = window;
}
void ApplicationController::loadFromFile(QString path)
{
if (!QFile::exists(path)) {
qWarning() << Q_FUNC_INFO << "no such file:" << path;
}
QFile f(path);
if (!f.open(QIODevice::ReadOnly)) {
qWarning() << Q_FUNC_INFO << "failed to open" << path;
return;
}
restoreState(f.readAll());
}
void ApplicationController::save(QString configName)
{
QDir d(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
@ -393,8 +415,12 @@ QByteArray ApplicationController::saveState(QString name) const
}
json["canvases"] = canvases;
if (m_window) {
json["window-rect"] = rectToJsonArray(m_window->geometry());
json["window-state"] = static_cast<int>(m_window->windowState());
}
// background color?
// window geometry and state?
QJsonDocument doc;
doc.setObject(json);
@ -408,7 +434,14 @@ void ApplicationController::restoreState(QByteArray bytes)
QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes);
QJsonObject json = jsonDoc.object();
// window size
if (m_window) {
QRect r = jsonArrayToRect(json.value("window-rect").toArray());
if (r.isValid()) {
m_window->setGeometry(r);
}
m_window->setWindowState(static_cast<Qt::WindowState>(json.value("window-state").toInt()));
}
// background color
for (auto c : json.value("canvases").toArray()) {

View file

@ -25,6 +25,7 @@
#include <QVariantList>
class CanvasConnection;
class QWindow;
class ApplicationController : public QObject
{
@ -44,10 +45,15 @@ class ApplicationController : public QObject
Q_ENUMS(Status)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
explicit ApplicationController(QObject *parent = nullptr);
~ApplicationController();
void setWindow(QWindow* window);
void loadFromFile(QString path);
Q_INVOKABLE void query();
Q_INVOKABLE void cancelQuery();
Q_INVOKABLE void clearQuery();
@ -140,6 +146,7 @@ private:
QVariantList m_configs;
QNetworkReply* m_query = nullptr;
QVariantList m_snapshots;
QWindow* m_window = nullptr;
};
#endif // APPLICATIONCONTROLLER_H

View file

@ -31,6 +31,7 @@
#include "localprop.h"
#include "fgqcanvasfontcache.h"
#include "fgqcanvasimageloader.h"
#include "jsonutils.h"
CanvasConnection::CanvasConnection(QObject *parent) : QObject(parent)
{
@ -65,7 +66,7 @@ QJsonObject CanvasConnection::saveState() const
QJsonObject json;
json["url"] = m_webSocketUrl.toString();
json["path"] = QString::fromUtf8(m_rootPropertyPath);
json["rect"] = QJsonArray{m_destRect.x(), m_destRect.y(), m_destRect.width(), m_destRect.height()};
json["rect"] = rectToJsonArray(m_destRect.toRect());
return json;
}
@ -73,13 +74,7 @@ bool CanvasConnection::restoreState(QJsonObject state)
{
m_webSocketUrl = state.value("url").toString();
m_rootPropertyPath = state.value("path").toString().toUtf8();
QJsonArray rect = state.value("rect").toArray();
if (rect.size() < 4) {
return false;
}
m_destRect = QRectF(rect[0].toDouble(), rect[1].toDouble(),
rect[2].toDouble(), rect[3].toDouble());
m_destRect = jsonArrayToRect(state.value("rect").toArray());
emit geometryChanged();
emit rootPathChanged();

View file

@ -33,6 +33,7 @@ CanvasPaintedDisplay::CanvasPaintedDisplay(QQuickItem* parent) :
CanvasPaintedDisplay::~CanvasPaintedDisplay()
{
qDebug() << "did destory canvas painted";
}
void CanvasPaintedDisplay::paint(QPainter *painter)
@ -47,6 +48,7 @@ void CanvasPaintedDisplay::paint(QPainter *painter)
FGCanvasPaintContext context(painter);
m_rootElement->paint(&context);
}
void CanvasPaintedDisplay::geometryChanged(const QRectF &newGeometry, const QRectF &)
@ -78,7 +80,6 @@ void CanvasPaintedDisplay::setCanvas(CanvasConnection *canvas)
onConnectionStatusChanged();
}
}
void CanvasPaintedDisplay::onConnectionDestroyed()
@ -94,24 +95,27 @@ void CanvasPaintedDisplay::onConnectionStatusChanged()
if ((m_connection->status() == CanvasConnection::Connected) ||
(m_connection->status() == CanvasConnection::Snapshot))
{
m_rootElement.reset(new FGCanvasGroup(nullptr, m_connection->propertyRoot()));
// this is important to elements can discover their connection
// by walking their parent chain
m_rootElement->setParent(m_connection);
connect(m_rootElement.get(), &FGCanvasGroup::canvasSizeChanged,
this, &CanvasPaintedDisplay::onCanvasSizeChanged);
onCanvasSizeChanged();
if (m_connection->status() == CanvasConnection::Snapshot) {
m_connection->propertyRoot()->recursiveNotifyRestored();
m_rootElement->polish();
update();
}
buildElements();
}
}
void CanvasPaintedDisplay::buildElements()
{
m_rootElement.reset(new FGCanvasGroup(nullptr, m_connection->propertyRoot()));
// this is important to elements can discover their connection
// by walking their parent chain
m_rootElement->setParent(m_connection);
connect(m_rootElement.get(), &FGCanvasGroup::canvasSizeChanged,
this, &CanvasPaintedDisplay::onCanvasSizeChanged);
onCanvasSizeChanged();
m_connection->propertyRoot()->recursiveNotifyRestored();
m_rootElement->polish();
update();
}
void CanvasPaintedDisplay::onConnectionUpdated()
{
if (m_rootElement) {

View file

@ -64,6 +64,7 @@ private slots:
private:
void recomputeScaling();
void buildElements();
CanvasConnection* m_connection = nullptr;
std::unique_ptr<FGCanvasGroup> m_rootElement;

View file

@ -158,6 +158,11 @@ void FGCanvasElement::polish()
_polishRequired = false;
}
void FGCanvasElement::dumpElement()
{
}
void FGCanvasElement::paint(FGCanvasPaintContext *context) const
{
if (!isVisible()) {
@ -297,7 +302,7 @@ bool FGCanvasElement::onChildAdded(LocalProp *prop)
// ignore for now, we do geo projection server-side
return true;
} else if (nm == "id") {
connect(prop, &LocalProp::valueChanged, [this](QVariant value) { _svgElementId = value.toByteArray(); });
connect(prop, &LocalProp::valueChanged, this, &FGCanvasElement::markSVGIDDirty);
return true;
} else if (prop->name() == "update") {
// disable updates optionally?
@ -483,6 +488,11 @@ void FGCanvasElement::markZIndexDirty(QVariant value)
_parent->markChildZIndicesDirty();
}
void FGCanvasElement::markSVGIDDirty(QVariant value)
{
_svgElementId = value.toByteArray();
}
void FGCanvasElement::onVisibleChanged(QVariant value)
{
_visible = value.toBool();

View file

@ -78,6 +78,7 @@ public:
void polish();
virtual void dumpElement() = 0;
protected:
virtual void doPaint(FGCanvasPaintContext* context) const;
@ -113,6 +114,7 @@ private:
void onVisibleChanged(QVariant value);
void markClipDirty();
void markSVGIDDirty(QVariant value);
private:
friend class FGCanvasGroup;

View file

@ -200,6 +200,15 @@ void FGCanvasGroup::removeChild(FGCanvasElement *child)
}
}
void FGCanvasGroup::dumpElement()
{
qDebug() << "Group at" << _propertyRoot->path();
for (auto c : _children) {
c->dumpElement();
}
qDebug() << "End-group at" << _propertyRoot->path();
}
int FGCanvasGroup::indexOfChildWithProp(LocalProp* prop) const
{
auto it = std::find_if(_children.begin(), _children.end(), [prop](FGCanvasElement* child)

View file

@ -26,6 +26,8 @@ public:
{ return _quick; }
void removeChild(FGCanvasElement* child);
void dumpElement() override;
signals:
void childAdded();
void childRemoved(int index);

View file

@ -386,6 +386,11 @@ FGCanvasPath::FGCanvasPath(FGCanvasGroup* pr, LocalProp* prop) :
{
}
void FGCanvasPath::dumpElement()
{
qDebug() << "Path: at " << _propertyRoot->path();
}
void FGCanvasPath::doPaint(FGCanvasPaintContext *context) const
{
context->painter()->setPen(_stroke);

View file

@ -30,6 +30,7 @@ class FGCanvasPath : public FGCanvasElement
public:
FGCanvasPath(FGCanvasGroup* pr, LocalProp* prop);
void dumpElement() override;
protected:
virtual void doPaint(FGCanvasPaintContext* context) const override;

View file

@ -202,6 +202,11 @@ CanvasItem *FGCanvasText::quickItem() const
return _quickItem;
}
void FGCanvasText::dumpElement()
{
qDebug() << "Text:" << _text << " at " << _propertyRoot->path();
}
void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
{
context->painter()->setFont(_font);

View file

@ -33,6 +33,7 @@ public:
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override;
void dumpElement() override;
protected:
virtual void doPaint(FGCanvasPaintContext* context) const override;
void doPolish() override;

View file

@ -256,4 +256,9 @@ CanvasItem *FGQCanvasImage::quickItem() const
return _quickItem;
}
void FGQCanvasImage::dumpElement()
{
qDebug() << "Image: " << _source << " at " << _propertyRoot->path();
}
#include "fgqcanvasimage.moc"

View file

@ -33,6 +33,8 @@ public:
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override;
void dumpElement() override;
protected:
virtual void doPaint(FGCanvasPaintContext* context) const override;

View file

@ -0,0 +1,34 @@
//
// Copyright (C) 2018 James Turner <james@flightgear.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "jsonutils.h"
QJsonArray rectToJsonArray(const QRect& r)
{
return QJsonArray{r.x(), r.y(), r.width(), r.height()};
}
QRect jsonArrayToRect(QJsonArray a)
{
if (a.size() < 4) {
return {};
}
return QRect(a[0].toInt(), a[1].toInt(),
a[2].toInt(), a[3].toInt());
}

View file

@ -0,0 +1,28 @@
//
// Copyright (C) 2018 James Turner <james@flightgear.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef JSONUTILS_H
#define JSONUTILS_H
#include <QRect>
#include <QJsonArray>
QJsonArray rectToJsonArray(const QRect& r);
QRect jsonArrayToRect(QJsonArray a);
#endif // JSONUTILS_H

View file

@ -35,7 +35,6 @@ int main(int argc, char *argv[])
a.setOrganizationName("FlightGear");
ApplicationController appController;
// load saved history on the app controller?
qmlRegisterType<CanvasItem>("FlightGear", 1, 0, "CanvasItem");
qmlRegisterType<CanvasDisplay>("FlightGear", 1, 0, "CanvasDisplay");
@ -45,10 +44,17 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<ApplicationController>("FlightGear", 1, 0, "Application", "Can't create");
QQuickView quickView;
quickView.resize(1024, 768);
appController.setWindow(&quickView);
quickView.rootContext()->setContextProperty("_application", &appController);
if (argc > 1) {
appController.loadFromFile(QString::fromLocal8Bit(argv[1]));
} else {
quickView.setWidth(1024);
quickView.setHeight(768);
}
quickView.setSource(QUrl("qrc:///qml/mainMenu.qml"));
quickView.setResizeMode(QQuickView::SizeRootObjectToView);
quickView.show();