FGQCanvas: load config on start mode
This commit is contained in:
parent
57fbd2fe01
commit
b0aa3b93b7
19 changed files with 181 additions and 29 deletions
|
@ -55,6 +55,8 @@ set(SOURCES
|
|||
canvasdisplay.h
|
||||
canvaspainteddisplay.cpp
|
||||
canvaspainteddisplay.h
|
||||
jsonutils.cpp
|
||||
jsonutils.h
|
||||
)
|
||||
|
||||
qt5_add_resources(qrc_sources fgqcanvas_resources.qrc)
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -64,6 +64,7 @@ private slots:
|
|||
|
||||
private:
|
||||
void recomputeScaling();
|
||||
void buildElements();
|
||||
|
||||
CanvasConnection* m_connection = nullptr;
|
||||
std::unique_ptr<FGCanvasGroup> m_rootElement;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
{ return _quick; }
|
||||
|
||||
void removeChild(FGCanvasElement* child);
|
||||
|
||||
void dumpElement() override;
|
||||
signals:
|
||||
void childAdded();
|
||||
void childRemoved(int index);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -256,4 +256,9 @@ CanvasItem *FGQCanvasImage::quickItem() const
|
|||
return _quickItem;
|
||||
}
|
||||
|
||||
void FGQCanvasImage::dumpElement()
|
||||
{
|
||||
qDebug() << "Image: " << _source << " at " << _propertyRoot->path();
|
||||
}
|
||||
|
||||
#include "fgqcanvasimage.moc"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
34
utils/fgqcanvas/jsonutils.cpp
Normal file
34
utils/fgqcanvas/jsonutils.cpp
Normal 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());
|
||||
}
|
28
utils/fgqcanvas/jsonutils.h
Normal file
28
utils/fgqcanvas/jsonutils.h
Normal 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
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue