From 61bf6b0f5884971492a3073b7806345d3fcd6bb5 Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 9 Jan 2017 16:55:03 +0000 Subject: [PATCH] QtQuick-based rendering for remote canvas Currently displayed alongside the QPainter version, while establishing the accuracy of each mode, but this is temporary. --- utils/fgqcanvas/CMakeLists.txt | 14 +- utils/fgqcanvas/canvasitem.cpp | 51 +++++ utils/fgqcanvas/canvasitem.h | 40 ++++ utils/fgqcanvas/canvastreemodel.cpp | 17 ++ utils/fgqcanvas/canvastreemodel.h | 17 ++ utils/fgqcanvas/elementdatamodel.cpp | 17 ++ utils/fgqcanvas/elementdatamodel.h | 17 ++ utils/fgqcanvas/fgcanvaselement.cpp | 51 ++++- utils/fgqcanvas/fgcanvaselement.h | 23 +++ utils/fgqcanvas/fgcanvasgroup.cpp | 20 +- utils/fgqcanvas/fgcanvasgroup.h | 6 + utils/fgqcanvas/fgcanvaspaintcontext.cpp | 19 +- utils/fgqcanvas/fgcanvaspaintcontext.h | 23 +++ utils/fgqcanvas/fgcanvaspath.cpp | 238 ++++++++++++++++++++++- utils/fgqcanvas/fgcanvaspath.h | 25 +++ utils/fgqcanvas/fgcanvastext.cpp | 56 +++++- utils/fgqcanvas/fgcanvastext.h | 23 +++ utils/fgqcanvas/fgcanvaswidget.cpp | 22 ++- utils/fgqcanvas/fgcanvaswidget.h | 17 ++ utils/fgqcanvas/fgqcanvasfontcache.cpp | 17 ++ utils/fgqcanvas/fgqcanvasfontcache.h | 17 ++ utils/fgqcanvas/fgqcanvasimage.cpp | 41 ++++ utils/fgqcanvas/fgqcanvasimage.h | 25 +++ utils/fgqcanvas/fgqcanvasimageloader.cpp | 17 ++ utils/fgqcanvas/fgqcanvasimageloader.h | 17 ++ utils/fgqcanvas/fgqcanvasmap.cpp | 17 ++ utils/fgqcanvas/fgqcanvasmap.h | 17 ++ utils/fgqcanvas/image.qml | 14 ++ utils/fgqcanvas/localprop.cpp | 17 ++ utils/fgqcanvas/localprop.h | 17 ++ utils/fgqcanvas/main.cpp | 24 +++ utils/fgqcanvas/root.qml | 5 + utils/fgqcanvas/temporarywidget.cpp | 155 +++++++++++---- utils/fgqcanvas/temporarywidget.h | 29 ++- utils/fgqcanvas/temporarywidget.ui | 84 +++++--- utils/fgqcanvas/text.qml | 18 ++ 36 files changed, 1140 insertions(+), 87 deletions(-) create mode 100644 utils/fgqcanvas/canvasitem.cpp create mode 100644 utils/fgqcanvas/canvasitem.h create mode 100644 utils/fgqcanvas/image.qml create mode 100644 utils/fgqcanvas/root.qml create mode 100644 utils/fgqcanvas/text.qml diff --git a/utils/fgqcanvas/CMakeLists.txt b/utils/fgqcanvas/CMakeLists.txt index ff626cd95..b1e81c324 100644 --- a/utils/fgqcanvas/CMakeLists.txt +++ b/utils/fgqcanvas/CMakeLists.txt @@ -6,11 +6,11 @@ include(GNUInstallDirs) project(FGQCanvas) -find_package(Qt5 5.4 COMPONENTS Widgets WebSockets) +find_package(Qt5 5.4 COMPONENTS Widgets WebSockets Gui Quick QuickWidgets) -if (NOT Qt5WebSockets_FOUND) - message(WARNING "FGQCanvas utility requested, but QtWebSockets not found") - message(STATUS "Check you have the development package for Qt5 WebSockets installed") +if (NOT Qt5WebSockets_FOUND OR NOT Qt5QuickWidgets_FOUND) + message(WARNING "FGQCanvas utility requested, but QtWebSockets/QtQuickWidgets not found") + message(STATUS "Check you have the development package for Qt5 WebSockets/QuickWidgets installed") return() endif() @@ -44,6 +44,8 @@ set(SOURCES fgqcanvasimageloader.h elementdatamodel.cpp elementdatamodel.h + canvasitem.cpp + canvasitem.h ) qt5_wrap_ui(uic_sources temporarywidget.ui) @@ -51,11 +53,13 @@ qt5_wrap_ui(uic_sources temporarywidget.ui) add_executable(fgqcanvas ${SOURCES} ${uic_sources}) set_property(TARGET fgqcanvas PROPERTY AUTOMOC ON) -target_link_libraries(fgqcanvas Qt5::Core Qt5::Widgets Qt5::WebSockets) +target_link_libraries(fgqcanvas Qt5::Core Qt5::Widgets Qt5::WebSockets Qt5::Quick Qt5::QuickWidgets) target_include_directories(fgqcanvas PRIVATE ${PROJECT_SOURCE_DIR}) # so ui_foo.h files are found target_include_directories(fgqcanvas PRIVATE ${PROJECT_BINARY_DIR}) +target_include_directories(fgqcanvas PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) + install(TARGETS fgqcanvas RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/utils/fgqcanvas/canvasitem.cpp b/utils/fgqcanvas/canvasitem.cpp new file mode 100644 index 000000000..fdf6bdd25 --- /dev/null +++ b/utils/fgqcanvas/canvasitem.cpp @@ -0,0 +1,51 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "canvasitem.h" + +#include + +class LocalTransform : public QQuickTransform +{ + Q_OBJECT +public: + LocalTransform(QObject *parent) : QQuickTransform(parent) {} + + void setTransform(const QMatrix4x4 &t) { + transform = t; + update(); + } + void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE { + *matrix *= transform; + } +private: + QMatrix4x4 transform; +}; + +CanvasItem::CanvasItem(QQuickItem* pr) + : QQuickItem(pr) + , m_localTransform(new LocalTransform(this)) +{ + m_localTransform->prependToItem(this); +} + +void CanvasItem::setTransform(const QMatrix4x4 &mat) +{ + m_localTransform->setTransform(mat); +} + +#include "canvasitem.moc" diff --git a/utils/fgqcanvas/canvasitem.h b/utils/fgqcanvas/canvasitem.h new file mode 100644 index 000000000..ebf46ae76 --- /dev/null +++ b/utils/fgqcanvas/canvasitem.h @@ -0,0 +1,40 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 CANVASITEM_H +#define CANVASITEM_H + +#include + +class LocalTransform; + +class CanvasItem : public QQuickItem +{ + Q_OBJECT +public: + CanvasItem(QQuickItem* pr = nullptr); + + void setTransform(const QMatrix4x4& mat); +signals: + +public slots: + +private: + LocalTransform* m_localTransform; +}; + +#endif // CANVASITEM_H diff --git a/utils/fgqcanvas/canvastreemodel.cpp b/utils/fgqcanvas/canvastreemodel.cpp index 7dd27728d..c0096c409 100644 --- a/utils/fgqcanvas/canvastreemodel.cpp +++ b/utils/fgqcanvas/canvastreemodel.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "canvastreemodel.h" #include diff --git a/utils/fgqcanvas/canvastreemodel.h b/utils/fgqcanvas/canvastreemodel.h index e9cc11e2f..9ee957d08 100644 --- a/utils/fgqcanvas/canvastreemodel.h +++ b/utils/fgqcanvas/canvastreemodel.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 CANVASTREEMODEL_H #define CANVASTREEMODEL_H diff --git a/utils/fgqcanvas/elementdatamodel.cpp b/utils/fgqcanvas/elementdatamodel.cpp index e1f79aa38..13787f20d 100644 --- a/utils/fgqcanvas/elementdatamodel.cpp +++ b/utils/fgqcanvas/elementdatamodel.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "elementdatamodel.h" #include "fgcanvaselement.h" diff --git a/utils/fgqcanvas/elementdatamodel.h b/utils/fgqcanvas/elementdatamodel.h index 9338352b4..a2cab899a 100644 --- a/utils/fgqcanvas/elementdatamodel.h +++ b/utils/fgqcanvas/elementdatamodel.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 ELEMENTDATAMODEL_H #define ELEMENTDATAMODEL_H diff --git a/utils/fgqcanvas/fgcanvaselement.cpp b/utils/fgqcanvas/fgcanvaselement.cpp index feec71f3d..d5b912d6e 100644 --- a/utils/fgqcanvas/fgcanvaselement.cpp +++ b/utils/fgqcanvas/fgcanvaselement.cpp @@ -1,13 +1,32 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgcanvaselement.h" #include "localprop.h" #include "fgcanvaspaintcontext.h" #include "fgcanvasgroup.h" +#include "canvasitem.h" #include #include #include #include +#include QTransform qTransformFromCanvas(LocalProp* prop) { @@ -50,6 +69,16 @@ bool FGCanvasElement::isHighlighted() const return _highlighted; } +CanvasItem *FGCanvasElement::createQuickItem(QQuickItem *parent) +{ + return nullptr; +} + +CanvasItem *FGCanvasElement::quickItem() const +{ + return nullptr; +} + FGCanvasElement::FGCanvasElement(FGCanvasGroup* pr, LocalProp* prop) : QObject(pr), _propertyRoot(prop), @@ -80,19 +109,31 @@ void FGCanvasElement::paint(FGCanvasPaintContext *context) const p->save(); - if (_hasClip) { -#if 0 + + if (_hasClip) + { + // clip is define in parent's coordinate system +#if 1 p->save(); + p->setTransform(context->globalCoordinateTransform()); p->setPen(Qt::yellow); p->setBrush(QBrush(Qt::yellow, Qt::DiagCrossPattern)); p->drawRect(_clipRect); p->restore(); #endif - context->painter()->setClipRect(_clipRect); - context->painter()->setClipping(true); + + QTransform t = p->transform(); + p->setTransform(context->globalCoordinateTransform()); + p->setClipRect(_clipRect); + p->setClipping(true); + p->setTransform(t); } - p->setTransform(combinedTransform(), true /* combine */); + QTransform combined = combinedTransform(); + p->setTransform(combined, true /* combine */); + if (quickItem()) { + quickItem()->setTransform(combined); + } if (_styleDirty) { _fillColor = parseColorValue(getCascadedStyle("fill")); diff --git a/utils/fgqcanvas/fgcanvaselement.h b/utils/fgqcanvas/fgcanvaselement.h index f5f1b9529..dee6164a1 100644 --- a/utils/fgqcanvas/fgcanvaselement.h +++ b/utils/fgqcanvas/fgcanvaselement.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGCANVASELEMENT_H #define FGCANVASELEMENT_H @@ -11,6 +28,8 @@ class LocalProp; class FGCanvasPaintContext; class FGCanvasGroup; +class CanvasItem; +class QQuickItem; class FGCanvasElement : public QObject { @@ -34,6 +53,10 @@ public: void setHighlighted(bool hilighted); bool isHighlighted() const; + + virtual CanvasItem* createQuickItem(QQuickItem* parent); + virtual CanvasItem* quickItem() const; + protected: virtual void doPaint(FGCanvasPaintContext* context) const; diff --git a/utils/fgqcanvas/fgcanvasgroup.cpp b/utils/fgqcanvas/fgcanvasgroup.cpp index a453a9247..88a4c35b8 100644 --- a/utils/fgqcanvas/fgcanvasgroup.cpp +++ b/utils/fgqcanvas/fgcanvasgroup.cpp @@ -2,6 +2,7 @@ #include +#include "canvasitem.h" #include "localprop.h" #include "fgcanvaspaintcontext.h" #include "fgcanvaspath.h" @@ -26,7 +27,6 @@ public: FGCanvasGroup::FGCanvasGroup(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasElement(pr, prop) { - } const FGCanvasElementVec &FGCanvasGroup::children() const @@ -65,6 +65,18 @@ unsigned int FGCanvasGroup::indexOfChild(const FGCanvasElement *e) const return std::distance(_children.begin(), it); } +CanvasItem *FGCanvasGroup::createQuickItem(QQuickItem *parent) +{ + qDebug() << Q_FUNC_INFO; + _quick = new CanvasItem(parent); + + for (auto e : _children) { + e->createQuickItem(_quick); + } + + return _quick; +} + void FGCanvasGroup::doPaint(FGCanvasPaintContext *context) const { if (_zIndicesDirty) { @@ -121,6 +133,12 @@ bool FGCanvasGroup::onChildAdded(LocalProp *prop) if (newChildCount > 0) { markChildZIndicesDirty(); + + if (_quick) { + qDebug() << "creating quick item for child"; + _children.back()->createQuickItem(_quick); + } + emit childAdded(); return true; } diff --git a/utils/fgqcanvas/fgcanvasgroup.h b/utils/fgqcanvas/fgcanvasgroup.h index 2696c14be..ca0953048 100644 --- a/utils/fgqcanvas/fgcanvasgroup.h +++ b/utils/fgqcanvas/fgcanvasgroup.h @@ -21,6 +21,10 @@ public: unsigned int indexOfChild(const FGCanvasElement* e) const; + CanvasItem* createQuickItem(QQuickItem *parent) override; + CanvasItem* quickItem() const override + { return _quick; } + signals: void childAdded(); void childRemoved(int index); @@ -40,6 +44,8 @@ private: mutable FGCanvasElementVec _children; mutable bool _zIndicesDirty = false; mutable bool _cachedSymbolDirty = false; + + CanvasItem* _quick = nullptr; }; #endif // FGCANVASGROUP_H diff --git a/utils/fgqcanvas/fgcanvaspaintcontext.cpp b/utils/fgqcanvas/fgcanvaspaintcontext.cpp index d25f534b7..ed3db3861 100644 --- a/utils/fgqcanvas/fgcanvaspaintcontext.cpp +++ b/utils/fgqcanvas/fgcanvaspaintcontext.cpp @@ -1,7 +1,24 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgcanvaspaintcontext.h" FGCanvasPaintContext::FGCanvasPaintContext(QPainter* painter) : _painter(painter) { - + _globalCoordsTransform = painter->transform(); } diff --git a/utils/fgqcanvas/fgcanvaspaintcontext.h b/utils/fgqcanvas/fgcanvaspaintcontext.h index 7b19de689..6b15b8e82 100644 --- a/utils/fgqcanvas/fgcanvaspaintcontext.h +++ b/utils/fgqcanvas/fgcanvaspaintcontext.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGCANVASPAINTCONTEXT_H #define FGCANVASPAINTCONTEXT_H @@ -11,8 +28,14 @@ public: QPainter* painter() const { return _painter; } + QTransform globalCoordinateTransform() const + { + return _globalCoordsTransform; + } + private: QPainter* _painter; + QTransform _globalCoordsTransform; }; #endif // FGCANVASPAINTCONTEXT_H diff --git a/utils/fgqcanvas/fgcanvaspath.cpp b/utils/fgqcanvas/fgcanvaspath.cpp index 56c9186da..275f5a3d4 100644 --- a/utils/fgqcanvas/fgcanvaspath.cpp +++ b/utils/fgqcanvas/fgcanvaspath.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgcanvaspath.h" #include @@ -6,9 +23,207 @@ #include #include #include +#include #include "fgcanvaspaintcontext.h" #include "localprop.h" +#include "canvasitem.h" + +#include "private/qtriangulator_p.h" // private QtGui header +#include "private/qtriangulatingstroker_p.h" // private QtGui header +#include "private/qvectorpath_p.h" // private QtGui header + +#include +#include +#include + +class PathQuickItem : public CanvasItem +{ + Q_OBJECT + + Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged) + Q_PROPERTY(QPen stroke READ stroke WRITE setStroke NOTIFY strokeChanged) + +public: + PathQuickItem(QQuickItem* parent) + : CanvasItem(parent) + { + setFlag(ItemHasContents); + } + + void setPath(QPainterPath pp) + { + m_path = pp; + + QRectF pathBounds = pp.boundingRect(); + setImplicitSize(pathBounds.width(), pathBounds.height()); + + update(); // request a paint node update + } + + virtual QSGNode* updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData *data) + { + if (m_path.isEmpty()) { + return nullptr; + } + + QSGGeometryNode* fillGeom = nullptr; + QSGGeometryNode* strokeGeom = nullptr; + + if (m_fillColor.isValid()) { + // TODO: compute LOD for qTriangulate based on world transform + QTransform transform; + QTriangleSet triangles = qTriangulate(m_path, transform); + + // TODO, handle > 2^16 indices + Q_ASSERT(triangles.indices.type() == QVertexIndexVector::UnsignedShort); + + QSGGeometry* sgGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), + triangles.vertices.size() >> 1, + triangles.indices.size()); + sgGeom->setIndexDataPattern(QSGGeometry::StaticPattern); + sgGeom->setDrawingMode(GL_TRIANGLES); + + // + QSGGeometry::Point2D *points = sgGeom->vertexDataAsPoint2D(); + for (int v=0; v < triangles.vertices.size(); ) { + const float vx = triangles.vertices.at(v++); + const float vy = triangles.vertices.at(v++); + (points++)->set(vx, vy); + } + + quint16* indices = sgGeom->indexDataAsUShort(); + ::memcpy(indices, triangles.indices.data(), sizeof(unsigned short) * triangles.indices.size()); + + // create the node now, pretty trivial + fillGeom = new QSGGeometryNode; + fillGeom->setGeometry(sgGeom); + fillGeom->setFlag(QSGNode::OwnsGeometry); + + QSGFlatColorMaterial* mat = new QSGFlatColorMaterial(); + mat->setColor(m_fillColor); + fillGeom->setMaterial(mat); + fillGeom->setFlag(QSGNode::OwnsMaterial); + } + + if (m_stroke.style() != Qt::NoPen) { + const QVectorPath& vp = qtVectorPathForPath(m_path); + QRectF clipBounds; + QTriangulatingStroker ts; + QPainter::RenderHints renderHints; + + if (m_stroke.style() == Qt::SolidLine) { + ts.process(vp, m_stroke, clipBounds, renderHints); + #if 0 + inline int vertexCount() const { return m_vertices.size(); } + inline const float *vertices() const { return m_vertices.data(); } + + #endif + } else { + QDashedStrokeProcessor dasher; + dasher.process(vp, m_stroke, clipBounds, renderHints); + + QVectorPath dashStroke(dasher.points(), + dasher.elementCount(), + dasher.elementTypes(), + renderHints); + + ts.process(dashStroke, m_stroke, clipBounds, renderHints); + } + + QSGGeometry* sgGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), + ts.vertexCount() >> 1); + sgGeom->setVertexDataPattern(QSGGeometry::StaticPattern); + sgGeom->setDrawingMode(GL_TRIANGLE_STRIP); + + QSGGeometry::Point2D *points = sgGeom->vertexDataAsPoint2D(); + const float* vPtr = ts.vertices(); + for (int v=0; v < ts.vertexCount(); v += 2) { + const float vx = *vPtr++; + const float vy = *vPtr++; + (points++)->set(vx, vy); + } + + // create the node now, pretty trivial + strokeGeom = new QSGGeometryNode; + strokeGeom->setGeometry(sgGeom); + strokeGeom->setFlag(QSGNode::OwnsGeometry); + + QSGFlatColorMaterial* mat = new QSGFlatColorMaterial(); + mat->setColor(m_stroke.color()); + strokeGeom->setMaterial(mat); + strokeGeom->setFlag(QSGNode::OwnsMaterial); + } + + if (fillGeom && strokeGeom) { + QSGNode* groupNode = new QSGNode; + groupNode->appendChildNode(fillGeom); + groupNode->appendChildNode(strokeGeom); + return groupNode; + } else if (fillGeom) { + return fillGeom; + } + + return strokeGeom; + } + + QColor fillColor() const + { + return m_fillColor; + } + + QPen stroke() const + { + return m_stroke; + } + +public slots: + void setFillColor(QColor fillColor) + { + if (m_fillColor == fillColor) + return; + + m_fillColor = fillColor; + emit fillColorChanged(fillColor); + update(); + } + + void setStroke(QPen stroke) + { + if (m_stroke == stroke) + return; + + m_stroke = stroke; + emit strokeChanged(stroke); + update(); + } + +signals: + void fillColorChanged(QColor fillColor); + + void strokeChanged(QPen stroke); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) + { + QQuickItem::geometryChanged(newGeometry, oldGeometry); + update(); + } + + QRectF boundingRect() const + { + if ((width() == 0.0) || (height() == 0.0)) { + return QRectF(0.0, 0.0, implicitWidth(), implicitHeight()); + } + + return QQuickItem::boundingRect(); + } + +private: + QPainterPath m_path; + QColor m_fillColor; + QPen m_stroke; +}; static void pathArcSegment(QPainterPath &path, qreal xc, qreal yc, @@ -155,18 +370,23 @@ static void pathArc(QPainterPath &path, FGCanvasPath::FGCanvasPath(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasElement(pr, prop) { - } void FGCanvasPath::doPaint(FGCanvasPaintContext *context) const { if (_pathDirty) { rebuildPath(); + if (_quickPath) { + _quickPath->setPath(_painterPath); + } _pathDirty = false; } if (_penDirty) { rebuildPen(); + if (_quickPath) { + _quickPath->setStroke(_stroke); + } _penDirty = false; } @@ -207,6 +427,20 @@ void FGCanvasPath::markStyleDirty() _penDirty = true; } +CanvasItem *FGCanvasPath::createQuickItem(QQuickItem *parent) +{ + qDebug() << Q_FUNC_INFO; + _quickPath = new PathQuickItem(parent); + _quickPath->setPath(_painterPath); + _quickPath->setStroke(_stroke); + return _quickPath; +} + +CanvasItem *FGCanvasPath::quickItem() const +{ + return _quickPath; +} + void FGCanvasPath::markPathDirty() { _pathDirty = true; @@ -693,3 +927,5 @@ void FGCanvasPath::rebuildPen() const _stroke = p; } + +#include "fgcanvaspath.moc" diff --git a/utils/fgqcanvas/fgcanvaspath.h b/utils/fgqcanvas/fgcanvaspath.h index 365ae6da6..d2099f035 100644 --- a/utils/fgqcanvas/fgcanvaspath.h +++ b/utils/fgqcanvas/fgcanvaspath.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGCANVASPATH_H #define FGCANVASPATH_H @@ -6,6 +23,8 @@ #include #include +class PathQuickItem; + class FGCanvasPath : public FGCanvasElement { public: @@ -15,6 +34,10 @@ protected: virtual void doPaint(FGCanvasPaintContext* context) const override; virtual void markStyleDirty() override; + + CanvasItem* createQuickItem(QQuickItem *parent) override; + CanvasItem* quickItem() const override; + private: void markPathDirty(); void markStrokeDirty(); @@ -44,6 +67,8 @@ private: mutable PaintType _paintType = Path; mutable QRectF _rect; mutable QSizeF _roundRectRadius; + + PathQuickItem* _quickPath = nullptr; }; #endif // FGCANVASPATH_H diff --git a/utils/fgqcanvas/fgcanvastext.cpp b/utils/fgqcanvas/fgcanvastext.cpp index e7ed7b85e..8d6c56a64 100644 --- a/utils/fgqcanvas/fgcanvastext.cpp +++ b/utils/fgqcanvas/fgcanvastext.cpp @@ -1,11 +1,33 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgcanvastext.h" #include #include +#include +#include #include "fgcanvaspaintcontext.h" #include "localprop.h" #include "fgqcanvasfontcache.h" +#include "canvasitem.h" + +static QQmlComponent* static_textComponent = nullptr; FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasElement(pr, prop), @@ -17,6 +39,26 @@ FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) : this, &FGCanvasText::onFontLoaded); } +CanvasItem *FGCanvasText::createQuickItem(QQuickItem *parent) +{ + Q_ASSERT(static_textComponent); + _quickItem = qobject_cast(static_textComponent->create()); + _quickItem->setParentItem(parent); + markFontDirty(); // so it gets set on the new item + return _quickItem; +} + +CanvasItem *FGCanvasText::quickItem() const +{ + return _quickItem; +} + +void FGCanvasText::setEngine(QQmlEngine *engine) +{ + static_textComponent = new QQmlComponent(engine, QUrl("text.qml")); + qDebug() << static_textComponent->errorString(); +} + void FGCanvasText::doPaint(FGCanvasPaintContext *context) const { if (_fontDirty) { @@ -82,6 +124,9 @@ bool FGCanvasText::onChildAdded(LocalProp *prop) void FGCanvasText::onTextChanged(QVariant var) { _text = var.toString(); + if (_quickItem) { + _quickItem->setProperty("text", var); + } } void FGCanvasText::setDrawMode(QVariant var) @@ -155,9 +200,18 @@ void FGCanvasText::rebuildFont() const // wait for the correct font } - f.setPixelSize(getCascadedStyle("character-size", 16).toInt()); + const int pixelSize = getCascadedStyle("character-size", 16).toInt(); + f.setPixelSize(pixelSize); _font = f; _metrics = QFontMetricsF(_font); rebuildAlignment(getCascadedStyle("alignment")); + + if (_quickItem) { + _quickItem->setProperty("fontFamily", f.family()); + _quickItem->setProperty("fontPixelSize", pixelSize); + + QColor fill = fillColor(); + _quickItem->setProperty("color", fill.name()); + } } diff --git a/utils/fgqcanvas/fgcanvastext.h b/utils/fgqcanvas/fgcanvastext.h index 4df31a638..179f8177f 100644 --- a/utils/fgqcanvas/fgcanvastext.h +++ b/utils/fgqcanvas/fgcanvastext.h @@ -1,8 +1,26 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGCANVASTEXT_H #define FGCANVASTEXT_H #include #include +#include #include "fgcanvaselement.h" @@ -11,7 +29,10 @@ class FGCanvasText : public FGCanvasElement public: FGCanvasText(FGCanvasGroup* pr, LocalProp* prop); + CanvasItem* createQuickItem(QQuickItem *parent) override; + CanvasItem* quickItem() const override; + static void setEngine(QQmlEngine* engine); protected: virtual void doPaint(FGCanvasPaintContext* context) const override; @@ -36,6 +57,8 @@ private: mutable bool _fontDirty = true; mutable QFont _font; mutable QFontMetricsF _metrics; + + CanvasItem* _quickItem = nullptr; }; diff --git a/utils/fgqcanvas/fgcanvaswidget.cpp b/utils/fgqcanvas/fgcanvaswidget.cpp index 5efbdf41b..93116de40 100644 --- a/utils/fgqcanvas/fgcanvaswidget.cpp +++ b/utils/fgqcanvas/fgcanvaswidget.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgcanvaswidget.h" #include @@ -37,7 +54,7 @@ void FGCanvasWidget::paintEvent(QPaintEvent *pe) QSizeF sz(_canvasRoot->value("size[0]", 512).toInt(), _canvasRoot->value("size[1]", 512).toInt()); - FGCanvasPaintContext context(&painter); + // set scaling by canvas size @@ -46,6 +63,9 @@ void FGCanvasWidget::paintEvent(QPaintEvent *pe) const double usedScale = std::min(verticalScaling, horizontalScaling); painter.scale(usedScale, usedScale); + + // captures the view scaling + FGCanvasPaintContext context(&painter); _rootElement->paint(&context); } diff --git a/utils/fgqcanvas/fgcanvaswidget.h b/utils/fgqcanvas/fgcanvaswidget.h index e7d0d9f6f..c95ad8bbd 100644 --- a/utils/fgqcanvas/fgcanvaswidget.h +++ b/utils/fgqcanvas/fgcanvaswidget.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGCANVASWIDGET_H #define FGCANVASWIDGET_H diff --git a/utils/fgqcanvas/fgqcanvasfontcache.cpp b/utils/fgqcanvas/fgqcanvasfontcache.cpp index 53b9bcf5e..85e6812d8 100644 --- a/utils/fgqcanvas/fgqcanvasfontcache.cpp +++ b/utils/fgqcanvas/fgqcanvasfontcache.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgqcanvasfontcache.h" #include diff --git a/utils/fgqcanvas/fgqcanvasfontcache.h b/utils/fgqcanvas/fgqcanvasfontcache.h index 7975f7c97..958a3ce4f 100644 --- a/utils/fgqcanvas/fgqcanvasfontcache.h +++ b/utils/fgqcanvas/fgqcanvasfontcache.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGQCANVASFONTCACHE_H #define FGQCANVASFONTCACHE_H diff --git a/utils/fgqcanvas/fgqcanvasimage.cpp b/utils/fgqcanvas/fgqcanvasimage.cpp index 310e0d4ad..7c4171b67 100644 --- a/utils/fgqcanvas/fgqcanvasimage.cpp +++ b/utils/fgqcanvas/fgqcanvasimage.cpp @@ -1,11 +1,32 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgqcanvasimage.h" #include #include +#include #include "fgcanvaspaintcontext.h" #include "localprop.h" #include "fgqcanvasimageloader.h" +#include "canvasitem.h" + +static QQmlComponent* static_imageComponent = nullptr; FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasElement(pr, prop) @@ -13,6 +34,12 @@ FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) : } +void FGQCanvasImage::setEngine(QQmlEngine *engine) +{ + static_imageComponent = new QQmlComponent(engine, QUrl("image.qml")); + qDebug() << static_imageComponent->errorString(); +} + void FGQCanvasImage::doPaint(FGCanvasPaintContext *context) const { if (_imageDirty) { @@ -117,3 +144,17 @@ void FGQCanvasImage::rebuildImage() const void FGQCanvasImage::markStyleDirty() { } + + +CanvasItem *FGQCanvasImage::createQuickItem(QQuickItem *parent) +{ + Q_ASSERT(static_imageComponent); + _quickItem = qobject_cast(static_imageComponent->create()); + _quickItem->setParentItem(parent); + return _quickItem; +} + +CanvasItem *FGQCanvasImage::quickItem() const +{ + return _quickItem; +} diff --git a/utils/fgqcanvas/fgqcanvasimage.h b/utils/fgqcanvas/fgqcanvasimage.h index 4752be8b1..a2e9bdc1d 100644 --- a/utils/fgqcanvas/fgqcanvasimage.h +++ b/utils/fgqcanvas/fgqcanvasimage.h @@ -1,7 +1,25 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGQCANVASIMAGE_H #define FGQCANVASIMAGE_H #include +#include #include "fgcanvaselement.h" @@ -11,11 +29,16 @@ class FGQCanvasImage : public FGCanvasElement public: FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop); + static void setEngine(QQmlEngine* engine); + + CanvasItem* createQuickItem(QQuickItem *parent) override; + CanvasItem* quickItem() const override; protected: virtual void doPaint(FGCanvasPaintContext* context) const override; virtual void markStyleDirty() override; + private slots: void markImageDirty(); void markSourceDirty(); @@ -33,6 +56,8 @@ private: QString _source; mutable QSizeF _destSize; mutable QRectF _sourceRect; + + CanvasItem* _quickItem = nullptr; }; #endif // FGQCANVASIMAGE_H diff --git a/utils/fgqcanvas/fgqcanvasimageloader.cpp b/utils/fgqcanvas/fgqcanvasimageloader.cpp index 0fce49b9f..c2f0aff02 100644 --- a/utils/fgqcanvas/fgqcanvasimageloader.cpp +++ b/utils/fgqcanvas/fgqcanvasimageloader.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgqcanvasimageloader.h" #include diff --git a/utils/fgqcanvas/fgqcanvasimageloader.h b/utils/fgqcanvas/fgqcanvasimageloader.h index 1ffa7d5b4..d0ded1108 100644 --- a/utils/fgqcanvas/fgqcanvasimageloader.h +++ b/utils/fgqcanvas/fgqcanvasimageloader.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGQCANVASIMAGELOADER_H #define FGQCANVASIMAGELOADER_H diff --git a/utils/fgqcanvas/fgqcanvasmap.cpp b/utils/fgqcanvas/fgqcanvasmap.cpp index 906199a66..fb49fab55 100644 --- a/utils/fgqcanvas/fgqcanvasmap.cpp +++ b/utils/fgqcanvas/fgqcanvasmap.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "fgqcanvasmap.h" #include diff --git a/utils/fgqcanvas/fgqcanvasmap.h b/utils/fgqcanvas/fgqcanvasmap.h index f0d529fa1..16104ffb0 100644 --- a/utils/fgqcanvas/fgqcanvasmap.h +++ b/utils/fgqcanvas/fgqcanvasmap.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 FGQCANVASMAP_H #define FGQCANVASMAP_H diff --git a/utils/fgqcanvas/image.qml b/utils/fgqcanvas/image.qml new file mode 100644 index 000000000..045d85698 --- /dev/null +++ b/utils/fgqcanvas/image.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import FlightGear 1.0 + +CanvasItem { + implicitHeight: img.implicitHeight + implicitWidth: img.implicitWidth + + property alias source: img.source + + Image { + id: img + + } +} diff --git a/utils/fgqcanvas/localprop.cpp b/utils/fgqcanvas/localprop.cpp index 014c3a58a..651528973 100644 --- a/utils/fgqcanvas/localprop.cpp +++ b/utils/fgqcanvas/localprop.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "localprop.h" #include diff --git a/utils/fgqcanvas/localprop.h b/utils/fgqcanvas/localprop.h index aa61d9134..9f28e42bd 100644 --- a/utils/fgqcanvas/localprop.h +++ b/utils/fgqcanvas/localprop.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 LOCALPROP_H #define LOCALPROP_H diff --git a/utils/fgqcanvas/main.cpp b/utils/fgqcanvas/main.cpp index fdfb1b1c8..d884d7499 100644 --- a/utils/fgqcanvas/main.cpp +++ b/utils/fgqcanvas/main.cpp @@ -1,15 +1,35 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "temporarywidget.h" #include #include #include #include +#include #include "fgqcanvasfontcache.h" #include "fgqcanvasimageloader.h" +#include "canvasitem.h" int main(int argc, char *argv[]) { + QApplication a(argc, argv); a.setApplicationName("FGCanvas"); @@ -25,7 +45,11 @@ int main(int argc, char *argv[]) FGQCanvasFontCache::initialise(downloader); FGQCanvasImageLoader::initialise(downloader); + qmlRegisterType("FlightGear", 1, 0, "CanvasItem"); + + TemporaryWidget w; + w.setNetworkAccess(downloader); w.show(); int result = a.exec(); diff --git a/utils/fgqcanvas/root.qml b/utils/fgqcanvas/root.qml new file mode 100644 index 000000000..37e0f7a2e --- /dev/null +++ b/utils/fgqcanvas/root.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Rectangle { + color: "black" +} diff --git a/utils/fgqcanvas/temporarywidget.cpp b/utils/fgqcanvas/temporarywidget.cpp index c951b4f1f..be5f73e93 100644 --- a/utils/fgqcanvas/temporarywidget.cpp +++ b/utils/fgqcanvas/temporarywidget.cpp @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 "temporarywidget.h" #include "ui_temporarywidget.h" @@ -7,20 +24,35 @@ #include #include #include +#include +#include +#include #include "fgqcanvasfontcache.h" #include "fgqcanvasimageloader.h" #include "canvastreemodel.h" #include "localprop.h" #include "elementdatamodel.h" +#include "fgcanvastext.h" +#include "fgqcanvasimage.h" TemporaryWidget::TemporaryWidget(QWidget *parent) : QWidget(parent), ui(new Ui::TemporaryWidget) { ui->setupUi(this); - connect(ui->connectButton, &QPushButton::clicked, this, &TemporaryWidget::onStartConnect); + connect(ui->connectButton, &QPushButton::clicked, this, &TemporaryWidget::onConnect); restoreSettings(); + + ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); + ui->quickWidget->setSource(QUrl("root.qml")); + + FGCanvasText::setEngine(ui->quickWidget->engine()); + FGQCanvasImage::setEngine(ui->quickWidget->engine()); + + connect(ui->canvasSelectCombo, SIGNAL(activated(int)), + this, SLOT(onCanvasSelected(int))); + ui->canvasSelectCombo->hide(); } TemporaryWidget::~TemporaryWidget() @@ -30,49 +62,77 @@ TemporaryWidget::~TemporaryWidget() delete ui; } -void TemporaryWidget::onStartConnect() +void TemporaryWidget::setNetworkAccess(QNetworkAccessManager *dl) { - QUrl wsUrl; - wsUrl.setScheme("ws"); - wsUrl.setHost(ui->hostName->text()); - wsUrl.setPort(ui->portEdit->text().toInt()); - -// string clean up, to ensure our root path has a leading slash but -// no trailing slash - QString propPath = ui->propertyPath->text(); - QString rootPath = propPath; - if (!propPath.startsWith('/')) { - rootPath = '/' + propPath; - } - - if (propPath.endsWith('/')) { - rootPath.chop(1); - } - - wsUrl.setPath("/PropertyTreeMirror" + rootPath); - rootPropertyPath = rootPath.toUtf8(); - - connect(&m_webSocket, &QWebSocket::connected, this, &TemporaryWidget::onConnected); - connect(&m_webSocket, &QWebSocket::disconnected, this, &TemporaryWidget::onSocketClosed); - - saveSettings(); - - qDebug() << "starting connection to:" << wsUrl; - m_webSocket.open(wsUrl); + m_netAccess = dl; } -void TemporaryWidget::onConnected() +void TemporaryWidget::onConnect() +{ + QUrl queryUrl; + queryUrl.setScheme("http"); + queryUrl.setHost(ui->hostName->text()); + queryUrl.setPort(ui->portEdit->text().toInt()); + queryUrl.setPath("/json/canvas/by-index"); + queryUrl.setQuery("d=2"); + + QNetworkReply* reply = m_netAccess->get(QNetworkRequest(queryUrl)); + connect(reply, &QNetworkReply::finished, this, &TemporaryWidget::onFinishedGetCanvasList); + + ui->connectButton->setEnabled(false); +} + +QJsonObject jsonPropNodeFindChild(QJsonObject obj, QByteArray name) +{ + Q_FOREACH (QJsonValue v, obj.value("children").toArray()) { + QJsonObject vo = v.toObject(); + if (vo.value("name").toString() == name) { + return vo; + } + } + + return QJsonObject(); +} + +void TemporaryWidget::onFinishedGetCanvasList() +{ + QNetworkReply* reply = qobject_cast(sender()); + reply->deleteLater(); + ui->connectButton->setEnabled(true); + + if (reply->error() != QNetworkReply::NoError) { + qWarning() << "failed to get canvases"; + // reset some state + return; + } + + ui->connectButton->hide(); + ui->canvasSelectCombo->show(); + + QJsonDocument json = QJsonDocument::fromJson(reply->readAll()); + + ui->canvasSelectCombo->clear(); + QJsonArray canvasArray = json.object().value("children").toArray(); + Q_FOREACH (QJsonValue canvasValue, canvasArray) { + QJsonObject canvas = canvasValue.toObject(); + QString canvasName = jsonPropNodeFindChild(canvas, "name").value("value").toString(); + QString propPath = canvas.value("path").toString(); + ui->canvasSelectCombo->addItem(canvasName, propPath); + } +} + +void TemporaryWidget::onWebSocketConnected() { - qDebug() << "connected"; connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &TemporaryWidget::onTextMessageReceived); - m_webSocket.sendTextMessage(QStringLiteral("Hello, world!")); m_localPropertyRoot = new LocalProp(nullptr, NameIndexTuple("")); ui->canvas->setRootProperty(m_localPropertyRoot); ui->stack->setCurrentIndex(1); + ui->canvas->rootElement()->createQuickItem(ui->quickWidget->rootObject()); + m_canvasModel = new CanvasTreeModel(ui->canvas->rootElement()); ui->treeView->setModel(m_canvasModel); @@ -85,7 +145,26 @@ void TemporaryWidget::onConnected() ui->portEdit->text().toInt()); FGQCanvasImageLoader::instance()->setHost(ui->hostName->text(), ui->portEdit->text().toInt()); - m_webSocket.sendTextMessage("nonsense"); +} + +void TemporaryWidget::onCanvasSelected(int index) +{ + QString path = ui->canvasSelectCombo->itemData(index).toString(); + + QUrl wsUrl; + wsUrl.setScheme("ws"); + wsUrl.setHost(ui->hostName->text()); + wsUrl.setPort(ui->portEdit->text().toInt()); + wsUrl.setPath("/PropertyTreeMirror" + path); + m_rootPropertyPath = path.toUtf8(); + + connect(&m_webSocket, &QWebSocket::connected, this, &TemporaryWidget::onWebSocketConnected); + connect(&m_webSocket, &QWebSocket::disconnected, this, &TemporaryWidget::onSocketClosed); + + saveSettings(); + + qDebug() << "starting connection to:" << wsUrl; + m_webSocket.open(wsUrl); } void TemporaryWidget::onTextMessageReceived(QString message) @@ -98,12 +177,12 @@ void TemporaryWidget::onTextMessageReceived(QString message) QJsonObject newProp = v.toObject(); QByteArray nodePath = newProp.value("path").toString().toUtf8(); - if (nodePath.indexOf(rootPropertyPath) != 0) { + if (nodePath.indexOf(m_rootPropertyPath) != 0) { qWarning() << "not a property path we are mirroring:" << nodePath; continue; } - QByteArray localPath = nodePath.mid(rootPropertyPath.size() + 1); + QByteArray localPath = nodePath.mid(m_rootPropertyPath.size() + 1); LocalProp* newNode = propertyFromPath(localPath); newNode->setPosition(newProp.value("position").toInt()); // store in the global dict @@ -163,7 +242,7 @@ void TemporaryWidget::onSocketClosed() ui->stack->setCurrentIndex(0); } -void TemporaryWidget::onTreeCurrentChanged(const QModelIndex &previous, const QModelIndex ¤t) +void TemporaryWidget::onTreeCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous) { FGCanvasElement* prev = m_canvasModel->elementFromIndex(previous); if (prev) { @@ -182,7 +261,7 @@ void TemporaryWidget::saveSettings() QSettings settings; settings.setValue("ws-host", ui->hostName->text()); settings.setValue("ws-port", ui->portEdit->text()); - settings.setValue("prop-path", ui->propertyPath->text()); + //settings.setValue("prop-path", ui->propertyPath->text()); } void TemporaryWidget::restoreSettings() @@ -190,7 +269,7 @@ void TemporaryWidget::restoreSettings() QSettings settings; ui->hostName->setText(settings.value("ws-host").toString()); ui->portEdit->setText(settings.value("ws-port").toString()); - ui->propertyPath->setText(settings.value("prop-path").toString()); + // ui->propertyPath->setText(settings.value("prop-path").toString()); } LocalProp *TemporaryWidget::propertyFromPath(QByteArray path) const diff --git a/utils/fgqcanvas/temporarywidget.h b/utils/fgqcanvas/temporarywidget.h index 8968598a1..402b6ded0 100644 --- a/utils/fgqcanvas/temporarywidget.h +++ b/utils/fgqcanvas/temporarywidget.h @@ -1,3 +1,20 @@ +// +// Copyright (C) 2017 James Turner zakalawe@mac.com +// +// 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 TEMPORARYWIDGET_H #define TEMPORARYWIDGET_H @@ -12,6 +29,7 @@ class TemporaryWidget; class LocalProp; class CanvasTreeModel; class ElementDataModel; +class QNetworkAccessManager; class TemporaryWidget : public QWidget { @@ -21,24 +39,29 @@ public: explicit TemporaryWidget(QWidget *parent = 0); ~TemporaryWidget(); + void setNetworkAccess(QNetworkAccessManager* dl); private Q_SLOTS: - void onStartConnect(); + void onConnect(); - void onConnected(); + void onWebSocketConnected(); void onTextMessageReceived(QString message); void onSocketClosed(); void onTreeCurrentChanged(const QModelIndex &previous, const QModelIndex ¤t); + void onCanvasSelected(int index); + + void onFinishedGetCanvasList(); private: void saveSettings(); void restoreSettings(); LocalProp* propertyFromPath(QByteArray path) const; + QNetworkAccessManager* m_netAccess; QWebSocket m_webSocket; Ui::TemporaryWidget *ui; - QByteArray rootPropertyPath; + QByteArray m_rootPropertyPath; LocalProp* m_localPropertyRoot = nullptr; QHash idPropertyDict; diff --git a/utils/fgqcanvas/temporarywidget.ui b/utils/fgqcanvas/temporarywidget.ui index 16ea8dd35..8a2b21b21 100644 --- a/utils/fgqcanvas/temporarywidget.ui +++ b/utils/fgqcanvas/temporarywidget.ui @@ -23,37 +23,7 @@ Connect - - - - - - - - Enter root property path: (eg '/canvas/by-index/texture[2]/') - - - - - - - Enter FlightGear host-name and port - - - - - - - - - - - - - Connect - - - + @@ -87,6 +57,39 @@ + + + + Enter FlightGear host-name and port + + + + + + + + + + + + + Select canvas: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Connect + + + + + + @@ -99,12 +102,31 @@ + + + Quick + + + + + + QQuickWidget::SizeRootObjectToView + + + + + + + QQuickWidget + QWidget +
QtQuickWidgets/QQuickWidget
+
FGCanvasWidget QWidget diff --git a/utils/fgqcanvas/text.qml b/utils/fgqcanvas/text.qml new file mode 100644 index 000000000..e5ff8e181 --- /dev/null +++ b/utils/fgqcanvas/text.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import FlightGear 1.0 + +CanvasItem { + implicitHeight: text.implicitHeight + implicitWidth: text.implicitWidth + + property alias text: text.text + property alias fontPixelSize: text.font.pixelSize + property alias fontFamily: text.font.family + property alias color: text.color + + Text { + id: text + font.pixelSize: 20 + color: "yellow" + } +}