1
0
Fork 0

QtQuick-based rendering for remote canvas

Currently displayed alongside the QPainter version, while establishing
the accuracy of each mode, but this is temporary.
This commit is contained in:
James Turner 2017-01-09 16:55:03 +00:00
parent 682c229313
commit 61bf6b0f58
36 changed files with 1140 additions and 87 deletions

View file

@ -6,11 +6,11 @@ include(GNUInstallDirs)
project(FGQCanvas) 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) if (NOT Qt5WebSockets_FOUND OR NOT Qt5QuickWidgets_FOUND)
message(WARNING "FGQCanvas utility requested, but QtWebSockets not found") message(WARNING "FGQCanvas utility requested, but QtWebSockets/QtQuickWidgets not found")
message(STATUS "Check you have the development package for Qt5 WebSockets installed") message(STATUS "Check you have the development package for Qt5 WebSockets/QuickWidgets installed")
return() return()
endif() endif()
@ -44,6 +44,8 @@ set(SOURCES
fgqcanvasimageloader.h fgqcanvasimageloader.h
elementdatamodel.cpp elementdatamodel.cpp
elementdatamodel.h elementdatamodel.h
canvasitem.cpp
canvasitem.h
) )
qt5_wrap_ui(uic_sources temporarywidget.ui) qt5_wrap_ui(uic_sources temporarywidget.ui)
@ -51,11 +53,13 @@ qt5_wrap_ui(uic_sources temporarywidget.ui)
add_executable(fgqcanvas ${SOURCES} ${uic_sources}) add_executable(fgqcanvas ${SOURCES} ${uic_sources})
set_property(TARGET fgqcanvas PROPERTY AUTOMOC ON) 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}) target_include_directories(fgqcanvas PRIVATE ${PROJECT_SOURCE_DIR})
# so ui_foo.h files are found # so ui_foo.h files are found
target_include_directories(fgqcanvas PRIVATE ${PROJECT_BINARY_DIR}) 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}) install(TARGETS fgqcanvas RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View file

@ -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 <QMatrix4x4>
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"

View file

@ -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 <QQuickItem>
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

View file

@ -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 "canvastreemodel.h"
#include <QDebug> #include <QDebug>

View file

@ -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 #ifndef CANVASTREEMODEL_H
#define CANVASTREEMODEL_H #define CANVASTREEMODEL_H

View file

@ -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 "elementdatamodel.h"
#include "fgcanvaselement.h" #include "fgcanvaselement.h"

View file

@ -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 #ifndef ELEMENTDATAMODEL_H
#define ELEMENTDATAMODEL_H #define ELEMENTDATAMODEL_H

View file

@ -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 "fgcanvaselement.h"
#include "localprop.h" #include "localprop.h"
#include "fgcanvaspaintcontext.h" #include "fgcanvaspaintcontext.h"
#include "fgcanvasgroup.h" #include "fgcanvasgroup.h"
#include "canvasitem.h"
#include <QDebug> #include <QDebug>
#include <QPainter> #include <QPainter>
#include <QRegularExpression> #include <QRegularExpression>
#include <QRegularExpressionMatch> #include <QRegularExpressionMatch>
#include <QMatrix4x4>
QTransform qTransformFromCanvas(LocalProp* prop) QTransform qTransformFromCanvas(LocalProp* prop)
{ {
@ -50,6 +69,16 @@ bool FGCanvasElement::isHighlighted() const
return _highlighted; return _highlighted;
} }
CanvasItem *FGCanvasElement::createQuickItem(QQuickItem *parent)
{
return nullptr;
}
CanvasItem *FGCanvasElement::quickItem() const
{
return nullptr;
}
FGCanvasElement::FGCanvasElement(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasElement::FGCanvasElement(FGCanvasGroup* pr, LocalProp* prop) :
QObject(pr), QObject(pr),
_propertyRoot(prop), _propertyRoot(prop),
@ -80,19 +109,31 @@ void FGCanvasElement::paint(FGCanvasPaintContext *context) const
p->save(); p->save();
if (_hasClip) {
#if 0 if (_hasClip)
{
// clip is define in parent's coordinate system
#if 1
p->save(); p->save();
p->setTransform(context->globalCoordinateTransform());
p->setPen(Qt::yellow); p->setPen(Qt::yellow);
p->setBrush(QBrush(Qt::yellow, Qt::DiagCrossPattern)); p->setBrush(QBrush(Qt::yellow, Qt::DiagCrossPattern));
p->drawRect(_clipRect); p->drawRect(_clipRect);
p->restore(); p->restore();
#endif #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) { if (_styleDirty) {
_fillColor = parseColorValue(getCascadedStyle("fill")); _fillColor = parseColorValue(getCascadedStyle("fill"));

View file

@ -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 #ifndef FGCANVASELEMENT_H
#define FGCANVASELEMENT_H #define FGCANVASELEMENT_H
@ -11,6 +28,8 @@
class LocalProp; class LocalProp;
class FGCanvasPaintContext; class FGCanvasPaintContext;
class FGCanvasGroup; class FGCanvasGroup;
class CanvasItem;
class QQuickItem;
class FGCanvasElement : public QObject class FGCanvasElement : public QObject
{ {
@ -34,6 +53,10 @@ public:
void setHighlighted(bool hilighted); void setHighlighted(bool hilighted);
bool isHighlighted() const; bool isHighlighted() const;
virtual CanvasItem* createQuickItem(QQuickItem* parent);
virtual CanvasItem* quickItem() const;
protected: protected:
virtual void doPaint(FGCanvasPaintContext* context) const; virtual void doPaint(FGCanvasPaintContext* context) const;

View file

@ -2,6 +2,7 @@
#include <QDebug> #include <QDebug>
#include "canvasitem.h"
#include "localprop.h" #include "localprop.h"
#include "fgcanvaspaintcontext.h" #include "fgcanvaspaintcontext.h"
#include "fgcanvaspath.h" #include "fgcanvaspath.h"
@ -26,7 +27,6 @@ public:
FGCanvasGroup::FGCanvasGroup(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasGroup::FGCanvasGroup(FGCanvasGroup* pr, LocalProp* prop) :
FGCanvasElement(pr, prop) FGCanvasElement(pr, prop)
{ {
} }
const FGCanvasElementVec &FGCanvasGroup::children() const const FGCanvasElementVec &FGCanvasGroup::children() const
@ -65,6 +65,18 @@ unsigned int FGCanvasGroup::indexOfChild(const FGCanvasElement *e) const
return std::distance(_children.begin(), it); 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 void FGCanvasGroup::doPaint(FGCanvasPaintContext *context) const
{ {
if (_zIndicesDirty) { if (_zIndicesDirty) {
@ -121,6 +133,12 @@ bool FGCanvasGroup::onChildAdded(LocalProp *prop)
if (newChildCount > 0) { if (newChildCount > 0) {
markChildZIndicesDirty(); markChildZIndicesDirty();
if (_quick) {
qDebug() << "creating quick item for child";
_children.back()->createQuickItem(_quick);
}
emit childAdded(); emit childAdded();
return true; return true;
} }

View file

@ -21,6 +21,10 @@ public:
unsigned int indexOfChild(const FGCanvasElement* e) const; unsigned int indexOfChild(const FGCanvasElement* e) const;
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override
{ return _quick; }
signals: signals:
void childAdded(); void childAdded();
void childRemoved(int index); void childRemoved(int index);
@ -40,6 +44,8 @@ private:
mutable FGCanvasElementVec _children; mutable FGCanvasElementVec _children;
mutable bool _zIndicesDirty = false; mutable bool _zIndicesDirty = false;
mutable bool _cachedSymbolDirty = false; mutable bool _cachedSymbolDirty = false;
CanvasItem* _quick = nullptr;
}; };
#endif // FGCANVASGROUP_H #endif // FGCANVASGROUP_H

View file

@ -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" #include "fgcanvaspaintcontext.h"
FGCanvasPaintContext::FGCanvasPaintContext(QPainter* painter) : FGCanvasPaintContext::FGCanvasPaintContext(QPainter* painter) :
_painter(painter) _painter(painter)
{ {
_globalCoordsTransform = painter->transform();
} }

View file

@ -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 #ifndef FGCANVASPAINTCONTEXT_H
#define FGCANVASPAINTCONTEXT_H #define FGCANVASPAINTCONTEXT_H
@ -11,8 +28,14 @@ public:
QPainter* painter() const QPainter* painter() const
{ return _painter; } { return _painter; }
QTransform globalCoordinateTransform() const
{
return _globalCoordsTransform;
}
private: private:
QPainter* _painter; QPainter* _painter;
QTransform _globalCoordsTransform;
}; };
#endif // FGCANVASPAINTCONTEXT_H #endif // FGCANVASPAINTCONTEXT_H

View file

@ -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 "fgcanvaspath.h"
#include <cctype> #include <cctype>
@ -6,9 +23,207 @@
#include <QPainter> #include <QPainter>
#include <QDebug> #include <QDebug>
#include <QtMath> #include <QtMath>
#include <QPen>
#include "fgcanvaspaintcontext.h" #include "fgcanvaspaintcontext.h"
#include "localprop.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 <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
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, static void pathArcSegment(QPainterPath &path,
qreal xc, qreal yc, qreal xc, qreal yc,
@ -155,18 +370,23 @@ static void pathArc(QPainterPath &path,
FGCanvasPath::FGCanvasPath(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasPath::FGCanvasPath(FGCanvasGroup* pr, LocalProp* prop) :
FGCanvasElement(pr, prop) FGCanvasElement(pr, prop)
{ {
} }
void FGCanvasPath::doPaint(FGCanvasPaintContext *context) const void FGCanvasPath::doPaint(FGCanvasPaintContext *context) const
{ {
if (_pathDirty) { if (_pathDirty) {
rebuildPath(); rebuildPath();
if (_quickPath) {
_quickPath->setPath(_painterPath);
}
_pathDirty = false; _pathDirty = false;
} }
if (_penDirty) { if (_penDirty) {
rebuildPen(); rebuildPen();
if (_quickPath) {
_quickPath->setStroke(_stroke);
}
_penDirty = false; _penDirty = false;
} }
@ -207,6 +427,20 @@ void FGCanvasPath::markStyleDirty()
_penDirty = true; _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() void FGCanvasPath::markPathDirty()
{ {
_pathDirty = true; _pathDirty = true;
@ -693,3 +927,5 @@ void FGCanvasPath::rebuildPen() const
_stroke = p; _stroke = p;
} }
#include "fgcanvaspath.moc"

View file

@ -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 #ifndef FGCANVASPATH_H
#define FGCANVASPATH_H #define FGCANVASPATH_H
@ -6,6 +23,8 @@
#include <QPainterPath> #include <QPainterPath>
#include <QPen> #include <QPen>
class PathQuickItem;
class FGCanvasPath : public FGCanvasElement class FGCanvasPath : public FGCanvasElement
{ {
public: public:
@ -15,6 +34,10 @@ protected:
virtual void doPaint(FGCanvasPaintContext* context) const override; virtual void doPaint(FGCanvasPaintContext* context) const override;
virtual void markStyleDirty() override; virtual void markStyleDirty() override;
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override;
private: private:
void markPathDirty(); void markPathDirty();
void markStrokeDirty(); void markStrokeDirty();
@ -44,6 +67,8 @@ private:
mutable PaintType _paintType = Path; mutable PaintType _paintType = Path;
mutable QRectF _rect; mutable QRectF _rect;
mutable QSizeF _roundRectRadius; mutable QSizeF _roundRectRadius;
PathQuickItem* _quickPath = nullptr;
}; };
#endif // FGCANVASPATH_H #endif // FGCANVASPATH_H

View file

@ -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 "fgcanvastext.h"
#include <QPainter> #include <QPainter>
#include <QDebug> #include <QDebug>
#include <QQmlComponent>
#include <QQmlEngine>
#include "fgcanvaspaintcontext.h" #include "fgcanvaspaintcontext.h"
#include "localprop.h" #include "localprop.h"
#include "fgqcanvasfontcache.h" #include "fgqcanvasfontcache.h"
#include "canvasitem.h"
static QQmlComponent* static_textComponent = nullptr;
FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) : FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
FGCanvasElement(pr, prop), FGCanvasElement(pr, prop),
@ -17,6 +39,26 @@ FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
this, &FGCanvasText::onFontLoaded); this, &FGCanvasText::onFontLoaded);
} }
CanvasItem *FGCanvasText::createQuickItem(QQuickItem *parent)
{
Q_ASSERT(static_textComponent);
_quickItem = qobject_cast<CanvasItem*>(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 void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
{ {
if (_fontDirty) { if (_fontDirty) {
@ -82,6 +124,9 @@ bool FGCanvasText::onChildAdded(LocalProp *prop)
void FGCanvasText::onTextChanged(QVariant var) void FGCanvasText::onTextChanged(QVariant var)
{ {
_text = var.toString(); _text = var.toString();
if (_quickItem) {
_quickItem->setProperty("text", var);
}
} }
void FGCanvasText::setDrawMode(QVariant var) void FGCanvasText::setDrawMode(QVariant var)
@ -155,9 +200,18 @@ void FGCanvasText::rebuildFont() const
// wait for the correct font // 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; _font = f;
_metrics = QFontMetricsF(_font); _metrics = QFontMetricsF(_font);
rebuildAlignment(getCascadedStyle("alignment")); rebuildAlignment(getCascadedStyle("alignment"));
if (_quickItem) {
_quickItem->setProperty("fontFamily", f.family());
_quickItem->setProperty("fontPixelSize", pixelSize);
QColor fill = fillColor();
_quickItem->setProperty("color", fill.name());
}
} }

View file

@ -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 #ifndef FGCANVASTEXT_H
#define FGCANVASTEXT_H #define FGCANVASTEXT_H
#include <QFont> #include <QFont>
#include <QFontMetricsF> #include <QFontMetricsF>
#include <QQmlEngine>
#include "fgcanvaselement.h" #include "fgcanvaselement.h"
@ -11,7 +29,10 @@ class FGCanvasText : public FGCanvasElement
public: public:
FGCanvasText(FGCanvasGroup* pr, LocalProp* prop); FGCanvasText(FGCanvasGroup* pr, LocalProp* prop);
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override;
static void setEngine(QQmlEngine* engine);
protected: protected:
virtual void doPaint(FGCanvasPaintContext* context) const override; virtual void doPaint(FGCanvasPaintContext* context) const override;
@ -36,6 +57,8 @@ private:
mutable bool _fontDirty = true; mutable bool _fontDirty = true;
mutable QFont _font; mutable QFont _font;
mutable QFontMetricsF _metrics; mutable QFontMetricsF _metrics;
CanvasItem* _quickItem = nullptr;
}; };

View file

@ -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 "fgcanvaswidget.h"
#include <QDebug> #include <QDebug>
@ -37,7 +54,7 @@ void FGCanvasWidget::paintEvent(QPaintEvent *pe)
QSizeF sz(_canvasRoot->value("size[0]", 512).toInt(), QSizeF sz(_canvasRoot->value("size[0]", 512).toInt(),
_canvasRoot->value("size[1]", 512).toInt()); _canvasRoot->value("size[1]", 512).toInt());
FGCanvasPaintContext context(&painter);
// set scaling by canvas size // set scaling by canvas size
@ -46,6 +63,9 @@ void FGCanvasWidget::paintEvent(QPaintEvent *pe)
const double usedScale = std::min(verticalScaling, horizontalScaling); const double usedScale = std::min(verticalScaling, horizontalScaling);
painter.scale(usedScale, usedScale); painter.scale(usedScale, usedScale);
// captures the view scaling
FGCanvasPaintContext context(&painter);
_rootElement->paint(&context); _rootElement->paint(&context);
} }

View file

@ -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 #ifndef FGCANVASWIDGET_H
#define FGCANVASWIDGET_H #define FGCANVASWIDGET_H

View file

@ -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 "fgqcanvasfontcache.h"
#include <QNetworkAccessManager> #include <QNetworkAccessManager>

View file

@ -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 #ifndef FGQCANVASFONTCACHE_H
#define FGQCANVASFONTCACHE_H #define FGQCANVASFONTCACHE_H

View file

@ -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 "fgqcanvasimage.h"
#include <QPainter> #include <QPainter>
#include <QDebug> #include <QDebug>
#include <QQmlComponent>
#include "fgcanvaspaintcontext.h" #include "fgcanvaspaintcontext.h"
#include "localprop.h" #include "localprop.h"
#include "fgqcanvasimageloader.h" #include "fgqcanvasimageloader.h"
#include "canvasitem.h"
static QQmlComponent* static_imageComponent = nullptr;
FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) : FGQCanvasImage::FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop) :
FGCanvasElement(pr, 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 void FGQCanvasImage::doPaint(FGCanvasPaintContext *context) const
{ {
if (_imageDirty) { if (_imageDirty) {
@ -117,3 +144,17 @@ void FGQCanvasImage::rebuildImage() const
void FGQCanvasImage::markStyleDirty() void FGQCanvasImage::markStyleDirty()
{ {
} }
CanvasItem *FGQCanvasImage::createQuickItem(QQuickItem *parent)
{
Q_ASSERT(static_imageComponent);
_quickItem = qobject_cast<CanvasItem*>(static_imageComponent->create());
_quickItem->setParentItem(parent);
return _quickItem;
}
CanvasItem *FGQCanvasImage::quickItem() const
{
return _quickItem;
}

View file

@ -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 #ifndef FGQCANVASIMAGE_H
#define FGQCANVASIMAGE_H #define FGQCANVASIMAGE_H
#include <QPixmap> #include <QPixmap>
#include <QQmlEngine>
#include "fgcanvaselement.h" #include "fgcanvaselement.h"
@ -11,11 +29,16 @@ class FGQCanvasImage : public FGCanvasElement
public: public:
FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop); FGQCanvasImage(FGCanvasGroup* pr, LocalProp* prop);
static void setEngine(QQmlEngine* engine);
CanvasItem* createQuickItem(QQuickItem *parent) override;
CanvasItem* quickItem() const override;
protected: protected:
virtual void doPaint(FGCanvasPaintContext* context) const override; virtual void doPaint(FGCanvasPaintContext* context) const override;
virtual void markStyleDirty() override; virtual void markStyleDirty() override;
private slots: private slots:
void markImageDirty(); void markImageDirty();
void markSourceDirty(); void markSourceDirty();
@ -33,6 +56,8 @@ private:
QString _source; QString _source;
mutable QSizeF _destSize; mutable QSizeF _destSize;
mutable QRectF _sourceRect; mutable QRectF _sourceRect;
CanvasItem* _quickItem = nullptr;
}; };
#endif // FGQCANVASIMAGE_H #endif // FGQCANVASIMAGE_H

View file

@ -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 "fgqcanvasimageloader.h"
#include <QDebug> #include <QDebug>

View file

@ -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 #ifndef FGQCANVASIMAGELOADER_H
#define FGQCANVASIMAGELOADER_H #define FGQCANVASIMAGELOADER_H

View file

@ -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 "fgqcanvasmap.h"
#include <QDebug> #include <QDebug>

View file

@ -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 #ifndef FGQCANVASMAP_H
#define FGQCANVASMAP_H #define FGQCANVASMAP_H

14
utils/fgqcanvas/image.qml Normal file
View file

@ -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
}
}

View file

@ -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 "localprop.h"
#include <QJsonValue> #include <QJsonValue>

View file

@ -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 #ifndef LOCALPROP_H
#define LOCALPROP_H #define LOCALPROP_H

View file

@ -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 "temporarywidget.h"
#include <QApplication> #include <QApplication>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkDiskCache> #include <QNetworkDiskCache>
#include <QStandardPaths> #include <QStandardPaths>
#include <QQmlEngine>
#include "fgqcanvasfontcache.h" #include "fgqcanvasfontcache.h"
#include "fgqcanvasimageloader.h" #include "fgqcanvasimageloader.h"
#include "canvasitem.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
a.setApplicationName("FGCanvas"); a.setApplicationName("FGCanvas");
@ -25,7 +45,11 @@ int main(int argc, char *argv[])
FGQCanvasFontCache::initialise(downloader); FGQCanvasFontCache::initialise(downloader);
FGQCanvasImageLoader::initialise(downloader); FGQCanvasImageLoader::initialise(downloader);
qmlRegisterType<CanvasItem>("FlightGear", 1, 0, "CanvasItem");
TemporaryWidget w; TemporaryWidget w;
w.setNetworkAccess(downloader);
w.show(); w.show();
int result = a.exec(); int result = a.exec();

5
utils/fgqcanvas/root.qml Normal file
View file

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: "black"
}

View file

@ -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 "temporarywidget.h"
#include "ui_temporarywidget.h" #include "ui_temporarywidget.h"
@ -7,20 +24,35 @@
#include <QJsonValue> #include <QJsonValue>
#include <QSettings> #include <QSettings>
#include <QItemSelectionModel> #include <QItemSelectionModel>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "fgqcanvasfontcache.h" #include "fgqcanvasfontcache.h"
#include "fgqcanvasimageloader.h" #include "fgqcanvasimageloader.h"
#include "canvastreemodel.h" #include "canvastreemodel.h"
#include "localprop.h" #include "localprop.h"
#include "elementdatamodel.h" #include "elementdatamodel.h"
#include "fgcanvastext.h"
#include "fgqcanvasimage.h"
TemporaryWidget::TemporaryWidget(QWidget *parent) : TemporaryWidget::TemporaryWidget(QWidget *parent) :
QWidget(parent), QWidget(parent),
ui(new Ui::TemporaryWidget) ui(new Ui::TemporaryWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->connectButton, &QPushButton::clicked, this, &TemporaryWidget::onStartConnect); connect(ui->connectButton, &QPushButton::clicked, this, &TemporaryWidget::onConnect);
restoreSettings(); 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() TemporaryWidget::~TemporaryWidget()
@ -30,49 +62,77 @@ TemporaryWidget::~TemporaryWidget()
delete ui; delete ui;
} }
void TemporaryWidget::onStartConnect() void TemporaryWidget::setNetworkAccess(QNetworkAccessManager *dl)
{ {
QUrl wsUrl; m_netAccess = dl;
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('/')) { void TemporaryWidget::onConnect()
rootPath.chop(1); {
} QUrl queryUrl;
queryUrl.setScheme("http");
wsUrl.setPath("/PropertyTreeMirror" + rootPath); queryUrl.setHost(ui->hostName->text());
rootPropertyPath = rootPath.toUtf8(); queryUrl.setPort(ui->portEdit->text().toInt());
queryUrl.setPath("/json/canvas/by-index");
connect(&m_webSocket, &QWebSocket::connected, this, &TemporaryWidget::onConnected); queryUrl.setQuery("d=2");
connect(&m_webSocket, &QWebSocket::disconnected, this, &TemporaryWidget::onSocketClosed);
QNetworkReply* reply = m_netAccess->get(QNetworkRequest(queryUrl));
saveSettings(); connect(reply, &QNetworkReply::finished, this, &TemporaryWidget::onFinishedGetCanvasList);
qDebug() << "starting connection to:" << wsUrl; ui->connectButton->setEnabled(false);
m_webSocket.open(wsUrl); }
}
QJsonObject jsonPropNodeFindChild(QJsonObject obj, QByteArray name)
void TemporaryWidget::onConnected() {
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<QNetworkReply*>(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, connect(&m_webSocket, &QWebSocket::textMessageReceived,
this, &TemporaryWidget::onTextMessageReceived); this, &TemporaryWidget::onTextMessageReceived);
m_webSocket.sendTextMessage(QStringLiteral("Hello, world!"));
m_localPropertyRoot = new LocalProp(nullptr, NameIndexTuple("")); m_localPropertyRoot = new LocalProp(nullptr, NameIndexTuple(""));
ui->canvas->setRootProperty(m_localPropertyRoot); ui->canvas->setRootProperty(m_localPropertyRoot);
ui->stack->setCurrentIndex(1); ui->stack->setCurrentIndex(1);
ui->canvas->rootElement()->createQuickItem(ui->quickWidget->rootObject());
m_canvasModel = new CanvasTreeModel(ui->canvas->rootElement()); m_canvasModel = new CanvasTreeModel(ui->canvas->rootElement());
ui->treeView->setModel(m_canvasModel); ui->treeView->setModel(m_canvasModel);
@ -85,7 +145,26 @@ void TemporaryWidget::onConnected()
ui->portEdit->text().toInt()); ui->portEdit->text().toInt());
FGQCanvasImageLoader::instance()->setHost(ui->hostName->text(), FGQCanvasImageLoader::instance()->setHost(ui->hostName->text(),
ui->portEdit->text().toInt()); 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) void TemporaryWidget::onTextMessageReceived(QString message)
@ -98,12 +177,12 @@ void TemporaryWidget::onTextMessageReceived(QString message)
QJsonObject newProp = v.toObject(); QJsonObject newProp = v.toObject();
QByteArray nodePath = newProp.value("path").toString().toUtf8(); 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; qWarning() << "not a property path we are mirroring:" << nodePath;
continue; continue;
} }
QByteArray localPath = nodePath.mid(rootPropertyPath.size() + 1); QByteArray localPath = nodePath.mid(m_rootPropertyPath.size() + 1);
LocalProp* newNode = propertyFromPath(localPath); LocalProp* newNode = propertyFromPath(localPath);
newNode->setPosition(newProp.value("position").toInt()); newNode->setPosition(newProp.value("position").toInt());
// store in the global dict // store in the global dict
@ -163,7 +242,7 @@ void TemporaryWidget::onSocketClosed()
ui->stack->setCurrentIndex(0); ui->stack->setCurrentIndex(0);
} }
void TemporaryWidget::onTreeCurrentChanged(const QModelIndex &previous, const QModelIndex &current) void TemporaryWidget::onTreeCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{ {
FGCanvasElement* prev = m_canvasModel->elementFromIndex(previous); FGCanvasElement* prev = m_canvasModel->elementFromIndex(previous);
if (prev) { if (prev) {
@ -182,7 +261,7 @@ void TemporaryWidget::saveSettings()
QSettings settings; QSettings settings;
settings.setValue("ws-host", ui->hostName->text()); settings.setValue("ws-host", ui->hostName->text());
settings.setValue("ws-port", ui->portEdit->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() void TemporaryWidget::restoreSettings()
@ -190,7 +269,7 @@ void TemporaryWidget::restoreSettings()
QSettings settings; QSettings settings;
ui->hostName->setText(settings.value("ws-host").toString()); ui->hostName->setText(settings.value("ws-host").toString());
ui->portEdit->setText(settings.value("ws-port").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 LocalProp *TemporaryWidget::propertyFromPath(QByteArray path) const

View file

@ -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 #ifndef TEMPORARYWIDGET_H
#define TEMPORARYWIDGET_H #define TEMPORARYWIDGET_H
@ -12,6 +29,7 @@ class TemporaryWidget;
class LocalProp; class LocalProp;
class CanvasTreeModel; class CanvasTreeModel;
class ElementDataModel; class ElementDataModel;
class QNetworkAccessManager;
class TemporaryWidget : public QWidget class TemporaryWidget : public QWidget
{ {
@ -21,24 +39,29 @@ public:
explicit TemporaryWidget(QWidget *parent = 0); explicit TemporaryWidget(QWidget *parent = 0);
~TemporaryWidget(); ~TemporaryWidget();
void setNetworkAccess(QNetworkAccessManager* dl);
private Q_SLOTS: private Q_SLOTS:
void onStartConnect(); void onConnect();
void onConnected(); void onWebSocketConnected();
void onTextMessageReceived(QString message); void onTextMessageReceived(QString message);
void onSocketClosed(); void onSocketClosed();
void onTreeCurrentChanged(const QModelIndex &previous, const QModelIndex &current); void onTreeCurrentChanged(const QModelIndex &previous, const QModelIndex &current);
void onCanvasSelected(int index);
void onFinishedGetCanvasList();
private: private:
void saveSettings(); void saveSettings();
void restoreSettings(); void restoreSettings();
LocalProp* propertyFromPath(QByteArray path) const; LocalProp* propertyFromPath(QByteArray path) const;
QNetworkAccessManager* m_netAccess;
QWebSocket m_webSocket; QWebSocket m_webSocket;
Ui::TemporaryWidget *ui; Ui::TemporaryWidget *ui;
QByteArray rootPropertyPath; QByteArray m_rootPropertyPath;
LocalProp* m_localPropertyRoot = nullptr; LocalProp* m_localPropertyRoot = nullptr;
QHash<int, LocalProp*> idPropertyDict; QHash<int, LocalProp*> idPropertyDict;

View file

@ -23,37 +23,7 @@
<attribute name="title"> <attribute name="title">
<string>Connect</string> <string>Connect</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,1,0" columnstretch="1,0"> <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,1" columnstretch="1,0">
<item row="1" column="1">
<widget class="QLineEdit" name="portEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Enter root property path: (eg '/canvas/by-index/texture[2]/')</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Enter FlightGear host-name and port</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="hostName"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLineEdit" name="propertyPath"/>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="connectButton">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2"> <item row="5" column="0" colspan="2">
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<property name="minimumSize"> <property name="minimumSize">
@ -87,6 +57,39 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Enter FlightGear host-name and port</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="portEdit"/>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="hostName"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="selectCanvasLabel">
<property name="text">
<string>Select canvas:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="connectButton">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="canvasSelectCombo"/>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="stackPage2"> <widget class="QWidget" name="stackPage2">
@ -99,12 +102,31 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Quick</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QQuickWidget" name="quickWidget">
<property name="resizeMode">
<enum>QQuickWidget::SizeRootObjectToView</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
<customwidget>
<class>QQuickWidget</class>
<extends>QWidget</extends>
<header>QtQuickWidgets/QQuickWidget</header>
</customwidget>
<customwidget> <customwidget>
<class>FGCanvasWidget</class> <class>FGCanvasWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>

18
utils/fgqcanvas/text.qml Normal file
View file

@ -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"
}
}