diff --git a/utils/fgqcanvas/CMakeLists.txt b/utils/fgqcanvas/CMakeLists.txt index fd8f0277c..85f38bd4c 100644 --- a/utils/fgqcanvas/CMakeLists.txt +++ b/utils/fgqcanvas/CMakeLists.txt @@ -55,6 +55,8 @@ set(SOURCES canvasdisplay.h canvaspainteddisplay.cpp canvaspainteddisplay.h + jsonutils.cpp + jsonutils.h ) qt5_add_resources(qrc_sources fgqcanvas_resources.qrc) diff --git a/utils/fgqcanvas/applicationcontroller.cpp b/utils/fgqcanvas/applicationcontroller.cpp index 798e4559f..37f84a9b4 100644 --- a/utils/fgqcanvas/applicationcontroller.cpp +++ b/utils/fgqcanvas/applicationcontroller.cpp @@ -32,7 +32,9 @@ #include #include #include +#include +#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(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(json.value("window-state").toInt())); + } // background color for (auto c : json.value("canvases").toArray()) { diff --git a/utils/fgqcanvas/applicationcontroller.h b/utils/fgqcanvas/applicationcontroller.h index ed931630a..26e2494f2 100644 --- a/utils/fgqcanvas/applicationcontroller.h +++ b/utils/fgqcanvas/applicationcontroller.h @@ -25,6 +25,7 @@ #include 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 diff --git a/utils/fgqcanvas/canvasconnection.cpp b/utils/fgqcanvas/canvasconnection.cpp index df88d58d2..8f34a398c 100644 --- a/utils/fgqcanvas/canvasconnection.cpp +++ b/utils/fgqcanvas/canvasconnection.cpp @@ -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(); diff --git a/utils/fgqcanvas/canvaspainteddisplay.cpp b/utils/fgqcanvas/canvaspainteddisplay.cpp index dd3203b27..0c01e657d 100644 --- a/utils/fgqcanvas/canvaspainteddisplay.cpp +++ b/utils/fgqcanvas/canvaspainteddisplay.cpp @@ -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) { diff --git a/utils/fgqcanvas/canvaspainteddisplay.h b/utils/fgqcanvas/canvaspainteddisplay.h index feea4ff97..31bdff856 100644 --- a/utils/fgqcanvas/canvaspainteddisplay.h +++ b/utils/fgqcanvas/canvaspainteddisplay.h @@ -64,6 +64,7 @@ private slots: private: void recomputeScaling(); + void buildElements(); CanvasConnection* m_connection = nullptr; std::unique_ptr m_rootElement; diff --git a/utils/fgqcanvas/fgcanvaselement.cpp b/utils/fgqcanvas/fgcanvaselement.cpp index 133af82cd..0a23521c3 100644 --- a/utils/fgqcanvas/fgcanvaselement.cpp +++ b/utils/fgqcanvas/fgcanvaselement.cpp @@ -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(); diff --git a/utils/fgqcanvas/fgcanvaselement.h b/utils/fgqcanvas/fgcanvaselement.h index 963c5dafb..ce9cf5d41 100644 --- a/utils/fgqcanvas/fgcanvaselement.h +++ b/utils/fgqcanvas/fgcanvaselement.h @@ -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; diff --git a/utils/fgqcanvas/fgcanvasgroup.cpp b/utils/fgqcanvas/fgcanvasgroup.cpp index 4ceac22bd..27f71f6fb 100644 --- a/utils/fgqcanvas/fgcanvasgroup.cpp +++ b/utils/fgqcanvas/fgcanvasgroup.cpp @@ -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) diff --git a/utils/fgqcanvas/fgcanvasgroup.h b/utils/fgqcanvas/fgcanvasgroup.h index 985eacba9..acccd2959 100644 --- a/utils/fgqcanvas/fgcanvasgroup.h +++ b/utils/fgqcanvas/fgcanvasgroup.h @@ -26,6 +26,8 @@ public: { return _quick; } void removeChild(FGCanvasElement* child); + + void dumpElement() override; signals: void childAdded(); void childRemoved(int index); diff --git a/utils/fgqcanvas/fgcanvaspath.cpp b/utils/fgqcanvas/fgcanvaspath.cpp index 8f0ee82b0..41bc88dd1 100644 --- a/utils/fgqcanvas/fgcanvaspath.cpp +++ b/utils/fgqcanvas/fgcanvaspath.cpp @@ -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); diff --git a/utils/fgqcanvas/fgcanvaspath.h b/utils/fgqcanvas/fgcanvaspath.h index 973697278..34f0dc227 100644 --- a/utils/fgqcanvas/fgcanvaspath.h +++ b/utils/fgqcanvas/fgcanvaspath.h @@ -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; diff --git a/utils/fgqcanvas/fgcanvastext.cpp b/utils/fgqcanvas/fgcanvastext.cpp index e32e91968..5fa1bd5d5 100644 --- a/utils/fgqcanvas/fgcanvastext.cpp +++ b/utils/fgqcanvas/fgcanvastext.cpp @@ -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); diff --git a/utils/fgqcanvas/fgcanvastext.h b/utils/fgqcanvas/fgcanvastext.h index 51c1f5833..7d0195b72 100644 --- a/utils/fgqcanvas/fgcanvastext.h +++ b/utils/fgqcanvas/fgcanvastext.h @@ -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; diff --git a/utils/fgqcanvas/fgqcanvasimage.cpp b/utils/fgqcanvas/fgqcanvasimage.cpp index 7750af5f5..c8102547a 100644 --- a/utils/fgqcanvas/fgqcanvasimage.cpp +++ b/utils/fgqcanvas/fgqcanvasimage.cpp @@ -256,4 +256,9 @@ CanvasItem *FGQCanvasImage::quickItem() const return _quickItem; } +void FGQCanvasImage::dumpElement() +{ + qDebug() << "Image: " << _source << " at " << _propertyRoot->path(); +} + #include "fgqcanvasimage.moc" diff --git a/utils/fgqcanvas/fgqcanvasimage.h b/utils/fgqcanvas/fgqcanvasimage.h index ae7f3cffd..9e4d02857 100644 --- a/utils/fgqcanvas/fgqcanvasimage.h +++ b/utils/fgqcanvas/fgqcanvasimage.h @@ -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; diff --git a/utils/fgqcanvas/jsonutils.cpp b/utils/fgqcanvas/jsonutils.cpp new file mode 100644 index 000000000..9c7e8637d --- /dev/null +++ b/utils/fgqcanvas/jsonutils.cpp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2018 James Turner +// +// 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()); +} diff --git a/utils/fgqcanvas/jsonutils.h b/utils/fgqcanvas/jsonutils.h new file mode 100644 index 000000000..f6166bce4 --- /dev/null +++ b/utils/fgqcanvas/jsonutils.h @@ -0,0 +1,28 @@ +// +// Copyright (C) 2018 James Turner +// +// 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 +#include + +QJsonArray rectToJsonArray(const QRect& r); + +QRect jsonArrayToRect(QJsonArray a); + +#endif // JSONUTILS_H diff --git a/utils/fgqcanvas/main.cpp b/utils/fgqcanvas/main.cpp index 041ffa93b..a33e6fd38 100644 --- a/utils/fgqcanvas/main.cpp +++ b/utils/fgqcanvas/main.cpp @@ -35,7 +35,6 @@ int main(int argc, char *argv[]) a.setOrganizationName("FlightGear"); ApplicationController appController; - // load saved history on the app controller? qmlRegisterType("FlightGear", 1, 0, "CanvasItem"); qmlRegisterType("FlightGear", 1, 0, "CanvasDisplay"); @@ -45,10 +44,17 @@ int main(int argc, char *argv[]) qmlRegisterUncreatableType("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();