1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-21 13:28:58 +01:00

Expose SVG elements geometry to QML side

This allows to reuse the existing svg file like pfd.svg
without manually positioning individual svg element.
This commit is contained in:
Dmytro Poplavskiy 2012-07-23 12:21:34 +10:00
parent 0c092970ca
commit 6ee34931ac
3 changed files with 73 additions and 25 deletions

View File

@ -31,15 +31,11 @@
#include "uavobjectmanager.h"
#include "uavobject.h"
#include <utils/stylehelper.h>
#include <utils/cachedsvgitem.h>
#include <iostream>
#include <QDebug>
#include <QPainter>
#include <QSvgRenderer>
#include <QtOpenGL/QGLWidget>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <cmath>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecontext.h>
@ -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));

View File

@ -31,6 +31,7 @@
#include <QUrl>
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());
}

View File

@ -28,19 +28,25 @@
#ifndef SVGIMAGEPROVIDER_H_
#define SVGIMAGEPROVIDER_H_
#include <QObject>
#include <QtDeclarative/qdeclarativeimageprovider.h>
#include <QSvgRenderer>
#include <QMap>
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<QString, QSvgRenderer*> m_renderers;
QString m_basePath;