diff --git a/ground/openpilotgcs/src/plugins/qmlview/qmlviewgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/qmlview/qmlviewgadgetwidget.cpp index cc4efe78d..a4c8f4f43 100644 --- a/ground/openpilotgcs/src/plugins/qmlview/qmlviewgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/qmlview/qmlviewgadgetwidget.cpp @@ -31,15 +31,11 @@ #include "uavobjectmanager.h" #include "uavobject.h" -#include -#include -#include #include -#include +#include #include #include #include -#include #include #include @@ -69,6 +65,8 @@ QmlViewGadgetWidget::QmlViewGadgetWidget(QWidget *parent) : else qWarning() << "Failed to load object" << objectName; } + + engine()->rootContext()->setContextProperty("qmlWidget", this); } QmlViewGadgetWidget::~QmlViewGadgetWidget() @@ -80,8 +78,12 @@ void QmlViewGadgetWidget::setQmlFile(QString fn) m_fn = fn; engine()->removeImageProvider("svg"); - engine()->addImageProvider("svg", - new SvgImageProvider(fn)); + SvgImageProvider *svgProvider = new SvgImageProvider(fn); + engine()->addImageProvider("svg", svgProvider); + + //it's necessary to allow qml side to query svg element position + engine()->rootContext()->setContextProperty("svgRenderer", svgProvider); + engine()->setBaseUrl(QUrl::fromLocalFile(fn)); qDebug() << Q_FUNC_INFO << fn; setSource(QUrl::fromLocalFile(fn)); diff --git a/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.cpp b/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.cpp index f44658090..e0f571369 100644 --- a/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.cpp +++ b/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.cpp @@ -31,6 +31,7 @@ #include SvgImageProvider::SvgImageProvider(const QString &basePath): + QObject(), QDeclarativeImageProvider(QDeclarativeImageProvider::Image), m_basePath(basePath) { @@ -41,6 +42,30 @@ SvgImageProvider::~SvgImageProvider() qDeleteAll(m_renderers); } +QSvgRenderer *SvgImageProvider::loadRenderer(const QString &svgFile) +{ + QSvgRenderer *renderer = m_renderers.value(svgFile); + if (!renderer) { + renderer = new QSvgRenderer(svgFile); + + QString fn = QUrl::fromLocalFile(m_basePath).resolved(svgFile).toLocalFile(); + + //convert path to be relative to base + if (!renderer->isValid()) + renderer->load(fn); + + if (!renderer->isValid()) { + qWarning() << "Failed to load svg file:" << svgFile << fn; + delete renderer; + return 0; + } + + m_renderers.insert(svgFile, renderer); + } + + return renderer; +} + /** requestedSize is realted to the whole svg file, not to specific element */ @@ -58,23 +83,9 @@ QImage SvgImageProvider::requestImage(const QString &id, QSize *size, const QSiz if (size) *size = QSize(); - QSvgRenderer *renderer = m_renderers.value(svgFile); - if (!renderer) { - renderer = new QSvgRenderer(svgFile); - - QString fn = QUrl::fromLocalFile(m_basePath).resolved(svgFile).toLocalFile(); - - //convert path to be relative to base - if (!renderer->isValid()) - renderer->load(fn); - - if (!renderer->isValid()) { - qWarning() << "Failed to load svg file:" << svgFile << fn; - return QImage(); - } - - m_renderers.insert(svgFile, renderer); - } + QSvgRenderer *renderer = loadRenderer(svgFile); + if (!renderer) + return QImage(); qreal xScale = 1.0; qreal yScale = 1.0; @@ -128,3 +139,32 @@ QPixmap SvgImageProvider::requestPixmap(const QString &id, QSize *size, const QS { return QPixmap::fromImage(requestImage(id, size, requestedSize)); } + +/*! + \fn SvgImageProvider::scaledElementBounds(const QString &svgFile, const QString &element) + + Returns the bound of \a element in logical coordinates, + scalled to the default size of svg document (so the bounds of whole doc would be (0,0,1,1) ). +*/ +QRectF SvgImageProvider::scaledElementBounds(const QString &svgFile, const QString &elementName) +{ + QSvgRenderer *renderer = loadRenderer(svgFile); + + if (!renderer) + return QRectF(); + + if (!renderer->elementExists(elementName)) { + qWarning() << "invalid element:" << elementName << "of" << svgFile; + return QRectF(); + } + + QRectF elementBounds = renderer->boundsOnElement(elementName); + QMatrix matrix = renderer->matrixForElement(elementName); + elementBounds = matrix.mapRect(elementBounds); + + QSize docSize = renderer->defaultSize(); + return QRectF(elementBounds.x()/docSize.width(), + elementBounds.y()/docSize.height(), + elementBounds.width()/docSize.width(), + elementBounds.height()/docSize.height()); +} diff --git a/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.h b/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.h index 1bcc20cee..50fd0f7bb 100644 --- a/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.h +++ b/ground/openpilotgcs/src/plugins/qmlview/svgimageprovider.h @@ -28,19 +28,25 @@ #ifndef SVGIMAGEPROVIDER_H_ #define SVGIMAGEPROVIDER_H_ +#include #include #include #include -class SvgImageProvider : public QDeclarativeImageProvider +class SvgImageProvider : public QObject, public QDeclarativeImageProvider { + Q_OBJECT public: SvgImageProvider(const QString &basePath); ~SvgImageProvider(); + QSvgRenderer *loadRenderer(const QString &svgFile); + QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize); + Q_INVOKABLE QRectF scaledElementBounds(const QString &svgFile, const QString &elementName); + private: QMap m_renderers; QString m_basePath;