1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

Header updates for Doxygen

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@892 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
dankers 2010-06-25 17:38:03 +00:00 committed by dankers
parent cdd3e305b0
commit 9ebfcf1617
20 changed files with 1308 additions and 1308 deletions

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedgadget.cpp
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedgadget.h
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedgadgetfactory.cpp
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedgadgetfactory.h
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -1,457 +1,457 @@
/**
******************************************************************************
*
* @file airspeedgadgetwidget.cpp
* @author David "Buzz" Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "airspeedgadgetwidget.h"
#include <iostream>
#include <QDebug>
AirspeedGadgetWidget::AirspeedGadgetWidget(QWidget *parent) : QGraphicsView(parent)
{
// TODO: create a proper "needle" object instead of hardcoding all this
// which is ugly (but easy).
setMinimumSize(64,64);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setScene(new QGraphicsScene(this));
setRenderHints(QPainter::Antialiasing);
m_renderer = new QSvgRenderer();
obj1 = NULL;
obj2 = NULL;
obj3 = NULL;
needle1Target = 0;
needle2Target = 0;
needle3Target = 0;
// This timer mechanism makes needles rotate smoothly
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
}
AirspeedGadgetWidget::~AirspeedGadgetWidget()
{
// Do nothing
}
/*!
\brief Connects the widget to the relevant UAVObjects
*/
void AirspeedGadgetWidget::connectNeedles(QString object1, QString nfield1,
QString object2, QString nfield2,
QString object3, QString nfield3) {
if (obj1 != NULL)
disconnect(obj1,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle1(UAVObject*)));
if (obj2 != NULL)
disconnect(obj2,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle2(UAVObject*)));
if (obj3 != NULL)
disconnect(obj3,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle3(UAVObject*)));
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
// Check validity of arguments first, reject empty args and unknown fields.
if (!(object1.isEmpty() || nfield1.isEmpty())) {
obj1 = dynamic_cast<UAVDataObject*>( objManager->getObject(object1) );
if (obj1 != NULL ) {
std::cout << "Connected Object 1 (" << object1.toStdString() << ")." << std::endl;
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle1(UAVObject*)));
field1 = nfield1;
} else {
std::cout << "Error: Object is unknown (" << object1.toStdString() << ")." << std::endl;
}
}
// And do the same for the second needle.
if (!(object2.isEmpty() || nfield2.isEmpty())) {
obj2 = dynamic_cast<UAVDataObject*>( objManager->getObject(object2) );
if (obj2 != NULL ) {
std::cout << "Connected Object 2 (" << object2.toStdString() << ")." << std::endl;
connect(obj2, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle2(UAVObject*)));
field2 = nfield2;
} else {
std::cout << "Error: Object is unknown (" << object2.toStdString() << ")." << std::endl;
}
}
// And do the same for the third needle.
if (!(object3.isEmpty() || nfield3.isEmpty())) {
obj3 = dynamic_cast<UAVDataObject*>( objManager->getObject(object3) );
if (obj3 != NULL ) {
std::cout << "Connected Object 3 (" << object3.toStdString() << ")." << std::endl;
connect(obj3, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle3(UAVObject*)));
field3 = nfield3;
} else {
std::cout << "Error: Object is unknown (" << object3.toStdString() << ")." << std::endl;
}
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle1(UAVObject *object1) {
// Double check that the field exists:
UAVObjectField* field = object1->getField(field1);
if (field) {
setNeedle1(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) {
UAVObjectField* field = object2->getField(field2);
if (field) {
setNeedle2(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle3(UAVObject *object3) {
UAVObjectField* field = object3->getField(field3);
if (field) {
setNeedle3(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*
Initializes the dial file, and does all the one-time calculations for
display later.
*/
void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2,
QString n3, QString n1Move, QString n2Move, QString n3Move)
{
if (QFile::exists(dfn))
{
m_renderer->load(dfn);
if(m_renderer->isValid())
{
fgenabled = false;
n2enabled = false;
n3enabled = false;
QGraphicsScene *l_scene = scene();
l_scene->clear(); // Deletes all items contained in the scene as well.
m_background = new QGraphicsSvgItem();
// All other items will be clipped to the shape of the background
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
m_foreground = new QGraphicsSvgItem();
m_needle1 = new QGraphicsSvgItem();
m_needle2 = new QGraphicsSvgItem();
m_needle3 = new QGraphicsSvgItem();
m_needle1->setParentItem(m_background);
m_needle2->setParentItem(m_background);
m_needle3->setParentItem(m_background);
m_foreground->setParentItem(m_background);
// We assume the dial contains at least the background
// and needle1
m_background->setSharedRenderer(m_renderer);
m_background->setElementId(bg);
l_scene->addItem(m_background);
m_needle1->setSharedRenderer(m_renderer);
m_needle1->setElementId(n1);
l_scene->addItem(m_needle1);
// The dial gadget allows Needle1 and Needle2 to be
// the same element, for combined movement. Needle3
// is always independent.
if (n1 == n2) {
m_needle2 = m_needle1;
n2enabled = true;
} else {
if (m_renderer->elementExists(n2)) {
m_needle2->setSharedRenderer(m_renderer);
m_needle2->setElementId(n2);
l_scene->addItem(m_needle2);
n2enabled = true;
}
}
if (m_renderer->elementExists(n3)) {
m_needle3->setSharedRenderer(m_renderer);
m_needle3->setElementId(n3);
l_scene->addItem(m_needle3);
n3enabled = true;
}
if (m_renderer->elementExists(fg)) {
m_foreground->setSharedRenderer(m_renderer);
m_foreground->setElementId(fg);
l_scene->addItem(m_foreground);
fgenabled = true;
}
rotateN1 = false;
horizN1 = false;
vertN1 = false;
rotateN2 = false;
horizN2 = false;
vertN2 = false;
rotateN3 = false;
horizN3 = false;
vertN3 = false;
// Now setup the rotation/translation settings:
// this is UGLY UGLY UGLY, sorry...
if (n1Move.contains("Rotate")) {
rotateN1 = true;
} else if (n1Move.contains("Horizontal")) {
horizN1 = true;
} else if (n1Move.contains("Vertical")) {
vertN1 = true;
}
if (n2Move.contains("Rotate")) {
rotateN2 = true;
} else if (n2Move.contains("Horizontal")) {
horizN2 = true;
} else if (n2Move.contains("Vertical")) {
vertN2 = true;
}
if (n3Move.contains("Rotate")) {
rotateN3 = true;
} else if (n3Move.contains("Horizontal")) {
horizN3 = true;
} else if (n3Move.contains("Vertical")) {
vertN3 = true;
}
l_scene->setSceneRect(m_background->boundingRect());
// Now Initialize the center for all transforms of the dial needles to the
// center of the background:
// - Move the center of the needle to the center of the background.
QRectF rectB = m_background->boundingRect();
QRectF rectN = m_needle1->boundingRect();
m_needle1->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
// - Put the transform origin point of the needle at its center.
m_needle1->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
if ((n1 != n2) && n2enabled) {
// Only do it for needle1 if it is not the same as n2
rectN = m_needle2->boundingRect();
m_needle2->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_needle2->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
}
if (n3enabled) {
rectN = m_needle3->boundingRect();
m_needle3->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_needle3->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
}
// Last: we just loaded the dial file which is by default valid for a "zero" value
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
// we would end up with an offset when we change a dial file and the needle value
// is not zero at that time.
needle1Value = 0;
needle2Value = 0;
needle3Value = 0;
if (!dialTimer.isActive())
dialTimer.start();
}
}
else
{ std::cout<<"no file: "<<std::endl; }
}
void AirspeedGadgetWidget::paint()
{
update();
}
void AirspeedGadgetWidget::paintEvent(QPaintEvent *event)
{
// Skip painting until the dial file is loaded
if (! m_renderer->isValid()) {
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
return;
}
QGraphicsView::paintEvent(event);
}
// This event enables the dial to be dynamically resized
// whenever the gadget is resized, taking advantage of the vector
// nature of SVG dials.
void AirspeedGadgetWidget::resizeEvent(QResizeEvent *event)
{
fitInView(m_background, Qt::KeepAspectRatio );
}
// Converts the value into an angle:
// this enables smooth rotation in rotateNeedles below
void AirspeedGadgetWidget::setNeedle1(double value) {
if (rotateN1) {
needle1Target = 360*value*n1Factor/(n1MaxValue-n1MinValue);
}
if (horizN1) {
needle1Target = value*n1Factor/(n1MaxValue-n1MinValue);
}
if (vertN1) {
needle1Target = value*n1Factor/(n1MaxValue-n1MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
void AirspeedGadgetWidget::setNeedle2(double value) {
if (rotateN2) {
needle2Target = 360*value*n2Factor/(n2MaxValue-n2MinValue);
}
if (horizN2) {
needle2Target = value*n2Factor/(n2MaxValue-n2MinValue);
}
if (vertN2) {
needle2Target = value*n2Factor/(n2MaxValue-n2MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
void AirspeedGadgetWidget::setNeedle3(double value) {
if (rotateN3) {
needle3Target = 360*value*n3Factor/(n3MaxValue-n3MinValue);
}
if (horizN3) {
needle3Target = value*n3Factor/(n3MaxValue-n3MinValue);
}
if (vertN3) {
needle3Target = value*n3Factor/(n3MaxValue-n3MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
// Take an input value and rotate the dial accordingly
// Rotation is smooth, starts fast and slows down when
// approaching the target.
// We aim for a 0.5 degree precision.
//
// Note: this code is valid even if needle1 and needle2 point
// to the same element.
void AirspeedGadgetWidget::rotateNeedles()
{
int dialRun = 3;
if (n2enabled) {
double needle2Diff;
if (abs((needle2Value-needle2Target)*10) > 5) {
needle2Diff =(needle2Target - needle2Value)/5;
} else {
needle2Diff = needle2Target - needle2Value;
dialRun--;
}
if (rotateN2) {
m_needle2->setRotation(m_needle2->rotation()+needle2Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN2) {
opd = QPointF(needle2Diff,0);
}
if (vertN2) {
opd = QPointF(0,needle2Diff);
}
m_needle2->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
// Since we have moved the needle, we need to move
// the transform origin point the opposite way
// so that it keeps rotating from the same point.
// (this is only useful if needle1 and needle2 are the
// same object, for combined movement such as attitude indicator).
QPointF oop = m_needle2->transformOriginPoint();
m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y());
}
needle2Value += needle2Diff;
} else {
dialRun--;
}
// We assume that needle1 always exists!
double needle1Diff;
if ((abs((needle1Value-needle1Target)*10) > 5)) {
needle1Diff = (needle1Target - needle1Value)/5;
} else {
needle1Diff = needle1Target - needle1Value;
dialRun--;
}
if (rotateN1) {
m_needle1->setRotation(m_needle1->rotation()+needle1Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN1) {
opd = QPointF(needle1Diff,0);
}
if (vertN1) {
opd = QPointF(0,needle1Diff);
}
m_needle1->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_needle1->transformOriginPoint();
m_needle1->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
}
needle1Value += needle1Diff;
if (n3enabled) {
double needle3Diff;
if ((abs((needle3Value-needle3Target)*10) > 5)) {
needle3Diff = (needle3Target - needle3Value)/5;
} else {
needle3Diff = needle3Target - needle3Value;
dialRun--;
}
if (rotateN3) {
m_needle3->setRotation(m_needle3->rotation()+needle3Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN3) {
opd = QPointF(needle3Diff,0);
}
if (vertN3) {
opd = QPointF(0,needle3Diff);
}
m_needle3->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_needle3->transformOriginPoint();
m_needle3->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
}
needle3Value += needle3Diff;
} else {
dialRun--;
}
//update();
// Now check: if dialRun is now zero, we should
// just stop the timer since all needles have finished moving
if (!dialRun) dialTimer.stop();
}
/**
******************************************************************************
*
* @file airspeedgadgetwidget.cpp
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "airspeedgadgetwidget.h"
#include <iostream>
#include <QDebug>
AirspeedGadgetWidget::AirspeedGadgetWidget(QWidget *parent) : QGraphicsView(parent)
{
// TODO: create a proper "needle" object instead of hardcoding all this
// which is ugly (but easy).
setMinimumSize(64,64);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setScene(new QGraphicsScene(this));
setRenderHints(QPainter::Antialiasing);
m_renderer = new QSvgRenderer();
obj1 = NULL;
obj2 = NULL;
obj3 = NULL;
needle1Target = 0;
needle2Target = 0;
needle3Target = 0;
// This timer mechanism makes needles rotate smoothly
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
}
AirspeedGadgetWidget::~AirspeedGadgetWidget()
{
// Do nothing
}
/*!
\brief Connects the widget to the relevant UAVObjects
*/
void AirspeedGadgetWidget::connectNeedles(QString object1, QString nfield1,
QString object2, QString nfield2,
QString object3, QString nfield3) {
if (obj1 != NULL)
disconnect(obj1,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle1(UAVObject*)));
if (obj2 != NULL)
disconnect(obj2,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle2(UAVObject*)));
if (obj3 != NULL)
disconnect(obj3,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle3(UAVObject*)));
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
// Check validity of arguments first, reject empty args and unknown fields.
if (!(object1.isEmpty() || nfield1.isEmpty())) {
obj1 = dynamic_cast<UAVDataObject*>( objManager->getObject(object1) );
if (obj1 != NULL ) {
std::cout << "Connected Object 1 (" << object1.toStdString() << ")." << std::endl;
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle1(UAVObject*)));
field1 = nfield1;
} else {
std::cout << "Error: Object is unknown (" << object1.toStdString() << ")." << std::endl;
}
}
// And do the same for the second needle.
if (!(object2.isEmpty() || nfield2.isEmpty())) {
obj2 = dynamic_cast<UAVDataObject*>( objManager->getObject(object2) );
if (obj2 != NULL ) {
std::cout << "Connected Object 2 (" << object2.toStdString() << ")." << std::endl;
connect(obj2, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle2(UAVObject*)));
field2 = nfield2;
} else {
std::cout << "Error: Object is unknown (" << object2.toStdString() << ")." << std::endl;
}
}
// And do the same for the third needle.
if (!(object3.isEmpty() || nfield3.isEmpty())) {
obj3 = dynamic_cast<UAVDataObject*>( objManager->getObject(object3) );
if (obj3 != NULL ) {
std::cout << "Connected Object 3 (" << object3.toStdString() << ")." << std::endl;
connect(obj3, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle3(UAVObject*)));
field3 = nfield3;
} else {
std::cout << "Error: Object is unknown (" << object3.toStdString() << ")." << std::endl;
}
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle1(UAVObject *object1) {
// Double check that the field exists:
UAVObjectField* field = object1->getField(field1);
if (field) {
setNeedle1(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) {
UAVObjectField* field = object2->getField(field2);
if (field) {
setNeedle2(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void AirspeedGadgetWidget::updateNeedle3(UAVObject *object3) {
UAVObjectField* field = object3->getField(field3);
if (field) {
setNeedle3(field->getDouble());
} else {
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*
Initializes the dial file, and does all the one-time calculations for
display later.
*/
void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2,
QString n3, QString n1Move, QString n2Move, QString n3Move)
{
if (QFile::exists(dfn))
{
m_renderer->load(dfn);
if(m_renderer->isValid())
{
fgenabled = false;
n2enabled = false;
n3enabled = false;
QGraphicsScene *l_scene = scene();
l_scene->clear(); // Deletes all items contained in the scene as well.
m_background = new QGraphicsSvgItem();
// All other items will be clipped to the shape of the background
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
m_foreground = new QGraphicsSvgItem();
m_needle1 = new QGraphicsSvgItem();
m_needle2 = new QGraphicsSvgItem();
m_needle3 = new QGraphicsSvgItem();
m_needle1->setParentItem(m_background);
m_needle2->setParentItem(m_background);
m_needle3->setParentItem(m_background);
m_foreground->setParentItem(m_background);
// We assume the dial contains at least the background
// and needle1
m_background->setSharedRenderer(m_renderer);
m_background->setElementId(bg);
l_scene->addItem(m_background);
m_needle1->setSharedRenderer(m_renderer);
m_needle1->setElementId(n1);
l_scene->addItem(m_needle1);
// The dial gadget allows Needle1 and Needle2 to be
// the same element, for combined movement. Needle3
// is always independent.
if (n1 == n2) {
m_needle2 = m_needle1;
n2enabled = true;
} else {
if (m_renderer->elementExists(n2)) {
m_needle2->setSharedRenderer(m_renderer);
m_needle2->setElementId(n2);
l_scene->addItem(m_needle2);
n2enabled = true;
}
}
if (m_renderer->elementExists(n3)) {
m_needle3->setSharedRenderer(m_renderer);
m_needle3->setElementId(n3);
l_scene->addItem(m_needle3);
n3enabled = true;
}
if (m_renderer->elementExists(fg)) {
m_foreground->setSharedRenderer(m_renderer);
m_foreground->setElementId(fg);
l_scene->addItem(m_foreground);
fgenabled = true;
}
rotateN1 = false;
horizN1 = false;
vertN1 = false;
rotateN2 = false;
horizN2 = false;
vertN2 = false;
rotateN3 = false;
horizN3 = false;
vertN3 = false;
// Now setup the rotation/translation settings:
// this is UGLY UGLY UGLY, sorry...
if (n1Move.contains("Rotate")) {
rotateN1 = true;
} else if (n1Move.contains("Horizontal")) {
horizN1 = true;
} else if (n1Move.contains("Vertical")) {
vertN1 = true;
}
if (n2Move.contains("Rotate")) {
rotateN2 = true;
} else if (n2Move.contains("Horizontal")) {
horizN2 = true;
} else if (n2Move.contains("Vertical")) {
vertN2 = true;
}
if (n3Move.contains("Rotate")) {
rotateN3 = true;
} else if (n3Move.contains("Horizontal")) {
horizN3 = true;
} else if (n3Move.contains("Vertical")) {
vertN3 = true;
}
l_scene->setSceneRect(m_background->boundingRect());
// Now Initialize the center for all transforms of the dial needles to the
// center of the background:
// - Move the center of the needle to the center of the background.
QRectF rectB = m_background->boundingRect();
QRectF rectN = m_needle1->boundingRect();
m_needle1->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
// - Put the transform origin point of the needle at its center.
m_needle1->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
if ((n1 != n2) && n2enabled) {
// Only do it for needle1 if it is not the same as n2
rectN = m_needle2->boundingRect();
m_needle2->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_needle2->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
}
if (n3enabled) {
rectN = m_needle3->boundingRect();
m_needle3->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_needle3->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
}
// Last: we just loaded the dial file which is by default valid for a "zero" value
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
// we would end up with an offset when we change a dial file and the needle value
// is not zero at that time.
needle1Value = 0;
needle2Value = 0;
needle3Value = 0;
if (!dialTimer.isActive())
dialTimer.start();
}
}
else
{ std::cout<<"no file: "<<std::endl; }
}
void AirspeedGadgetWidget::paint()
{
update();
}
void AirspeedGadgetWidget::paintEvent(QPaintEvent *event)
{
// Skip painting until the dial file is loaded
if (! m_renderer->isValid()) {
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
return;
}
QGraphicsView::paintEvent(event);
}
// This event enables the dial to be dynamically resized
// whenever the gadget is resized, taking advantage of the vector
// nature of SVG dials.
void AirspeedGadgetWidget::resizeEvent(QResizeEvent *event)
{
fitInView(m_background, Qt::KeepAspectRatio );
}
// Converts the value into an angle:
// this enables smooth rotation in rotateNeedles below
void AirspeedGadgetWidget::setNeedle1(double value) {
if (rotateN1) {
needle1Target = 360*value*n1Factor/(n1MaxValue-n1MinValue);
}
if (horizN1) {
needle1Target = value*n1Factor/(n1MaxValue-n1MinValue);
}
if (vertN1) {
needle1Target = value*n1Factor/(n1MaxValue-n1MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
void AirspeedGadgetWidget::setNeedle2(double value) {
if (rotateN2) {
needle2Target = 360*value*n2Factor/(n2MaxValue-n2MinValue);
}
if (horizN2) {
needle2Target = value*n2Factor/(n2MaxValue-n2MinValue);
}
if (vertN2) {
needle2Target = value*n2Factor/(n2MaxValue-n2MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
void AirspeedGadgetWidget::setNeedle3(double value) {
if (rotateN3) {
needle3Target = 360*value*n3Factor/(n3MaxValue-n3MinValue);
}
if (horizN3) {
needle3Target = value*n3Factor/(n3MaxValue-n3MinValue);
}
if (vertN3) {
needle3Target = value*n3Factor/(n3MaxValue-n3MinValue);
}
if (!dialTimer.isActive())
dialTimer.start();
}
// Take an input value and rotate the dial accordingly
// Rotation is smooth, starts fast and slows down when
// approaching the target.
// We aim for a 0.5 degree precision.
//
// Note: this code is valid even if needle1 and needle2 point
// to the same element.
void AirspeedGadgetWidget::rotateNeedles()
{
int dialRun = 3;
if (n2enabled) {
double needle2Diff;
if (abs((needle2Value-needle2Target)*10) > 5) {
needle2Diff =(needle2Target - needle2Value)/5;
} else {
needle2Diff = needle2Target - needle2Value;
dialRun--;
}
if (rotateN2) {
m_needle2->setRotation(m_needle2->rotation()+needle2Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN2) {
opd = QPointF(needle2Diff,0);
}
if (vertN2) {
opd = QPointF(0,needle2Diff);
}
m_needle2->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
// Since we have moved the needle, we need to move
// the transform origin point the opposite way
// so that it keeps rotating from the same point.
// (this is only useful if needle1 and needle2 are the
// same object, for combined movement such as attitude indicator).
QPointF oop = m_needle2->transformOriginPoint();
m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y());
}
needle2Value += needle2Diff;
} else {
dialRun--;
}
// We assume that needle1 always exists!
double needle1Diff;
if ((abs((needle1Value-needle1Target)*10) > 5)) {
needle1Diff = (needle1Target - needle1Value)/5;
} else {
needle1Diff = needle1Target - needle1Value;
dialRun--;
}
if (rotateN1) {
m_needle1->setRotation(m_needle1->rotation()+needle1Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN1) {
opd = QPointF(needle1Diff,0);
}
if (vertN1) {
opd = QPointF(0,needle1Diff);
}
m_needle1->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_needle1->transformOriginPoint();
m_needle1->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
}
needle1Value += needle1Diff;
if (n3enabled) {
double needle3Diff;
if ((abs((needle3Value-needle3Target)*10) > 5)) {
needle3Diff = (needle3Target - needle3Value)/5;
} else {
needle3Diff = needle3Target - needle3Value;
dialRun--;
}
if (rotateN3) {
m_needle3->setRotation(m_needle3->rotation()+needle3Diff);
} else {
QPointF opd = QPointF(0,0);
if (horizN3) {
opd = QPointF(needle3Diff,0);
}
if (vertN3) {
opd = QPointF(0,needle3Diff);
}
m_needle3->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_needle3->transformOriginPoint();
m_needle3->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
}
needle3Value += needle3Diff;
} else {
dialRun--;
}
//update();
// Now check: if dialRun is now zero, we should
// just stop the timer since all needles have finished moving
if (!dialRun) dialTimer.stop();
}

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedgadgetwidget.h
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedplugin.h
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -2,7 +2,7 @@
******************************************************************************
*
* @file airspeedplugin.h
* @author David "Buzz" Carlson Copyright (C) 2010.
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup dialplugin

View File

@ -1,60 +1,60 @@
/**
******************************************************************************
*
* @file airspeedgadget.cpp
* @author David "Buzz" Carlson Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup airspeed
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadget.h"
#include "pfdgadgetwidget.h"
#include "pfdgadgetconfiguration.h"
PFDGadget::PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent),
m_widget(widget)
{
}
PFDGadget::~PFDGadget()
{
}
/*
This is called when a configuration is loaded, and updates the plugin's settings.
Careful: the plugin is already drawn before the loadConfiguration method is called the
first time, so you have to be careful not to assume all the plugin values are initialized
the first time you use them
*/
void PFDGadget::loadConfiguration(IUAVGadgetConfiguration* config)
{
PFDGadgetConfiguration *m = qobject_cast<PFDGadgetConfiguration*>(config);
m_widget->setDialFile(m->dialFile());
m_widget->setN2Min(m->getN2Min());
m_widget->setN2Max(m->getN2Max());
m_widget->setN2Factor(m->getN2Factor());
m_widget->setN3Min(m->getN3Min());
m_widget->setN3Max(m->getN3Max());
m_widget->setN3Factor(m->getN3Factor());
m_widget->connectNeedles();
}
/**
******************************************************************************
*
* @file pfdgadget.cpp
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadget.h"
#include "pfdgadgetwidget.h"
#include "pfdgadgetconfiguration.h"
PFDGadget::PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent),
m_widget(widget)
{
}
PFDGadget::~PFDGadget()
{
}
/*
This is called when a configuration is loaded, and updates the plugin's settings.
Careful: the plugin is already drawn before the loadConfiguration method is called the
first time, so you have to be careful not to assume all the plugin values are initialized
the first time you use them
*/
void PFDGadget::loadConfiguration(IUAVGadgetConfiguration* config)
{
PFDGadgetConfiguration *m = qobject_cast<PFDGadgetConfiguration*>(config);
m_widget->setDialFile(m->dialFile());
m_widget->setN2Min(m->getN2Min());
m_widget->setN2Max(m->getN2Max());
m_widget->setN2Factor(m->getN2Factor());
m_widget->setN3Min(m->getN3Min());
m_widget->setN3Max(m->getN3Max());
m_widget->setN3Factor(m->getN3Factor());
m_widget->connectNeedles();
}

View File

@ -1,56 +1,56 @@
/**
******************************************************************************
*
* @file pfdgadget.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGET_H_
#define PFDGADGET_H_
#include <coreplugin/iuavgadget.h>
#include "pfdgadgetwidget.h"
class IUAVGadget;
class QWidget;
class QString;
class PFDGadgetWidget;
using namespace Core;
class PFDGadget : public Core::IUAVGadget
{
Q_OBJECT
public:
PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent = 0);
~PFDGadget();
QWidget *widget() { return m_widget; }
void loadConfiguration(IUAVGadgetConfiguration* config);
private:
PFDGadgetWidget *m_widget;
};
#endif // PFDGADGET_H_
/**
******************************************************************************
*
* @file pfdgadget.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGET_H_
#define PFDGADGET_H_
#include <coreplugin/iuavgadget.h>
#include "pfdgadgetwidget.h"
class IUAVGadget;
class QWidget;
class QString;
class PFDGadgetWidget;
using namespace Core;
class PFDGadget : public Core::IUAVGadget
{
Q_OBJECT
public:
PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent = 0);
~PFDGadget();
QWidget *widget() { return m_widget; }
void loadConfiguration(IUAVGadgetConfiguration* config);
private:
PFDGadgetWidget *m_widget;
};
#endif // PFDGADGET_H_

View File

@ -5,7 +5,7 @@
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Primary Flight Display Plugin Gadget configuration
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @defgroup pfdplugin
* @{
*
*****************************************************************************/

View File

@ -5,7 +5,7 @@
* @author Edouard Lafargue Copyright (C) 2010.
* @brief Primary Flight Display Plugin Gadget configuration
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @defgroup pfdplugin
* @{
*
*****************************************************************************/

View File

@ -1,60 +1,60 @@
/**
******************************************************************************
*
* @file pfdgadgetfactory.cpp
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadgetfactory.h"
#include "pfdgadgetwidget.h"
#include "pfdgadget.h"
#include "pfdgadgetconfiguration.h"
#include "pfdgadgetoptionspage.h"
#include <coreplugin/iuavgadget.h>
PFDGadgetFactory::PFDGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("PFDGadget"),
tr("Primary Flight Display Gadget"),
parent)
{
}
PFDGadgetFactory::~PFDGadgetFactory()
{
}
Core::IUAVGadget* PFDGadgetFactory::createGadget(QWidget *parent)
{
PFDGadgetWidget* gadgetWidget = new PFDGadgetWidget(parent);
return new PFDGadget(QString("PFDGadget"), gadgetWidget, parent);
}
IUAVGadgetConfiguration *PFDGadgetFactory::createConfiguration(const QByteArray &state)
{
return new PFDGadgetConfiguration(QString("PFDGadget"), state);
}
IOptionsPage *PFDGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new PFDGadgetOptionsPage(qobject_cast<PFDGadgetConfiguration*>(config));
}
/**
******************************************************************************
*
* @file pfdgadgetfactory.cpp
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadgetfactory.h"
#include "pfdgadgetwidget.h"
#include "pfdgadget.h"
#include "pfdgadgetconfiguration.h"
#include "pfdgadgetoptionspage.h"
#include <coreplugin/iuavgadget.h>
PFDGadgetFactory::PFDGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("PFDGadget"),
tr("Primary Flight Display Gadget"),
parent)
{
}
PFDGadgetFactory::~PFDGadgetFactory()
{
}
Core::IUAVGadget* PFDGadgetFactory::createGadget(QWidget *parent)
{
PFDGadgetWidget* gadgetWidget = new PFDGadgetWidget(parent);
return new PFDGadget(QString("PFDGadget"), gadgetWidget, parent);
}
IUAVGadgetConfiguration *PFDGadgetFactory::createConfiguration(const QByteArray &state)
{
return new PFDGadgetConfiguration(QString("PFDGadget"), state);
}
IOptionsPage *PFDGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new PFDGadgetOptionsPage(qobject_cast<PFDGadgetConfiguration*>(config));
}

View File

@ -1,52 +1,52 @@
/**
******************************************************************************
*
* @file pfdgadgetfactory.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGETFACTORY_H_
#define PFDGADGETFACTORY_H_
#include <coreplugin/iuavgadgetfactory.h>
namespace Core {
class IUAVGadget;
class IUAVGadgetFactory;
}
using namespace Core;
class PFDGadgetFactory : public IUAVGadgetFactory
{
Q_OBJECT
public:
PFDGadgetFactory(QObject *parent = 0);
~PFDGadgetFactory();
Core::IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(const QByteArray &state);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
};
#endif // PFDGADGETFACTORY_H_
/**
******************************************************************************
*
* @file pfdgadgetfactory.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGETFACTORY_H_
#define PFDGADGETFACTORY_H_
#include <coreplugin/iuavgadgetfactory.h>
namespace Core {
class IUAVGadget;
class IUAVGadgetFactory;
}
using namespace Core;
class PFDGadgetFactory : public IUAVGadgetFactory
{
Q_OBJECT
public:
PFDGadgetFactory(QObject *parent = 0);
~PFDGadgetFactory();
Core::IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(const QByteArray &state);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
};
#endif // PFDGADGETFACTORY_H_

View File

@ -5,7 +5,7 @@
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Primary Flight Display Plugin Gadget options page
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @defgroup pfdplugin
* @{
*
*****************************************************************************/

View File

@ -5,7 +5,7 @@
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Primary Flight Display Plugin Gadget options page
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @defgroup pfdplugin
* @{
*
*****************************************************************************/

View File

@ -1,371 +1,371 @@
/**
******************************************************************************
*
* @file pfdgadgetwidget.cpp
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadgetwidget.h"
#include <iostream>
#include <QDebug>
PFDGadgetWidget::PFDGadgetWidget(QWidget *parent) : QGraphicsView(parent)
{
// TODO: create a proper "needle" object instead of hardcoding all this
// which is ugly (but easy).
setMinimumSize(64,64);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setScene(new QGraphicsScene(this));
setRenderHints(QPainter::Antialiasing);
m_renderer = new QSvgRenderer();
attitudeObj = NULL;
headingObj = NULL;
compassBandWidth = 0;
/*
obj2 = NULL;
obj3 = NULL;
*/
// This timer mechanism makes needles rotate smoothly
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
dialTimer.start(20);
}
PFDGadgetWidget::~PFDGadgetWidget()
{
// Do nothing
}
/*!
\brief Connects the widget to the relevant UAVObjects
We want: AttitudeActual, FlightBattery, Location
*/
void PFDGadgetWidget::connectNeedles() {
if (attitudeObj != NULL)
disconnect(attitudeObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateAttitude(UAVObject*)));
if (headingObj != NULL)
disconnect(headingObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateHeading(UAVObject*)));
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
attitudeObj = dynamic_cast<UAVDataObject*>(objManager->getObject("AttitudeActual"));
if (attitudeObj != NULL ) {
connect(attitudeObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateAttitude(UAVObject*)));
} else {
std::cout << "Error: Object is unknown (AttitudeActual)." << std::endl;
}
headingObj = dynamic_cast<UAVDataObject*>(objManager->getObject("PositionActual"));
if (headingObj != NULL ) {
connect(headingObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateHeading(UAVObject*)));
} else {
std::cout << "Error: Object is unknown (PositionActual)." << std::endl;
}
}
/*!
\brief Reads the updated attitude and computes the new display position
*/
void PFDGadgetWidget::updateAttitude(UAVObject *object1) {
// Double check that the field exists:
QString roll = QString("Roll");
QString pitch = QString("Pitch");
UAVObjectField* field = object1->getField(roll);
UAVObjectField* field2 = object1->getField(pitch);
if (field && field2) {
// These factors assume some things about the PFD SVG, namely:
// - Roll value in degrees
// - Pitch lines are 300px high for a +20/-20 range, which means
// 7.5 pixels per pitch degree.
rollTarget = field->getDouble()*(-1);
pitchTarget = field2->getDouble()*7.5;
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
} else {
std::cout << "UpdateAttitude: Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateHeading(UAVObject *object1) {
// Double check that the field exists:
QString heading = QString("Heading");
UAVObjectField* field = object1->getField(heading);
if (field) {
// These factors assume some things about the PFD SVG, namely:
// - Heading value in degrees
// - Scale is 540 degrees large
headingTarget = field->getDouble()*compassBandWidth/(-540);
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
} else {
std::cout << "UpdateHeading: Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateAirspeed(UAVObject *object3) {
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateAltitude(UAVObject *object3) {
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateBattery(UAVObject *object3) {
}
/*
Initializes the dial file, and does all the one-time calculations for
display later.
*/
void PFDGadgetWidget::setDialFile(QString dfn)
{
if (QFile::exists(dfn))
{
m_renderer->load(dfn);
if(m_renderer->isValid())
{
/* The PFD element IDs are fixed, not like with the analog dial.
- Background: background
- Foreground: foreground (contains all fixed elements, including plane)
- earth/sky : world
- Roll scale: rollscale
- compass frame: compass (part of the foreground)
- compass band : compass-band
- Home point: homewaypoint
- Next point: nextwaypoint
- Home point bearing: homewaypoint-bearing
- Next point bearing: nextwaypoint-bearing
*/
QGraphicsScene *l_scene = scene();
l_scene->clear(); // Deletes all items contained in the scene as well.
m_background = new QGraphicsSvgItem();
// All other items will be clipped to the shape of the background
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
m_background->setSharedRenderer(m_renderer);
m_background->setElementId("background");
l_scene->addItem(m_background);
m_world = new QGraphicsSvgItem();
m_world->setParentItem(m_background);
m_world->setSharedRenderer(m_renderer);
m_world->setElementId("world");
l_scene->addItem(m_world);
// red Roll scale: rollscale
m_rollscale = new QGraphicsSvgItem();
m_rollscale->setSharedRenderer(m_renderer);
m_rollscale->setElementId("rollscale");
l_scene->addItem(m_rollscale);
// Home point:
m_homewaypoint = new QGraphicsSvgItem();
// Next point:
m_nextwaypoint = new QGraphicsSvgItem();
// Home point bearing:
m_homepointbearing = new QGraphicsSvgItem();
// Next point bearing:
m_nextpointbearing = new QGraphicsSvgItem();
m_foreground = new QGraphicsSvgItem();
m_foreground->setParentItem(m_background);
m_foreground->setSharedRenderer(m_renderer);
m_foreground->setElementId("foreground");
l_scene->addItem(m_foreground);
// Compass:
// Get the default location of the Compass:
QMatrix compassMatrix = m_renderer->matrixForElement("compass");
qreal startX = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).x();
qreal startY = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).y();
// Then once we have the initial location, we can put it
// into a QGraphicsSvgItem which we will display at the same
// place: we do this so that the heading scale can be clipped to
// the compass dial region.
m_compass = new QGraphicsSvgItem();
m_compass->setSharedRenderer(m_renderer);
m_compass->setElementId("compass");
m_compass->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
l_scene->addItem(m_compass);
QTransform matrix;
matrix.translate(startX,startY);
m_compass->setTransform(matrix,false);
// Now place the compass scale inside:
m_compassband = new QGraphicsSvgItem();
m_compassband->setSharedRenderer(m_renderer);
m_compassband->setElementId("compass-band");
m_compassband->setParentItem(m_compass);
l_scene->addItem(m_compassband);
matrix.reset();
// Note: the compass band has to be a path, which means all text elements have to be
// converted, ortherwise boundsOnElement does not compute the height correctly
// if the highest element is a text element. This is a Qt Bug as far as I can tell.
// compass-scale is the while bottom line inside the band: using the band's width
// includes half the width of the letters, which causes errors:
compassBandWidth = m_renderer->boundsOnElement("compass-scale").width();
l_scene->setSceneRect(m_background->boundingRect());
// Now Initialize the center for all transforms of the relevant elements to the
// center of the background:
// 1) Move the center of the needle to the center of the background.
QRectF rectB = m_background->boundingRect();
QRectF rectN = m_world->boundingRect();
m_world->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
// 2) Put the transform origin point of the needle at its center.
m_world->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
rectN = m_rollscale->boundingRect();
m_rollscale->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_rollscale->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
// Also to the same init for the compass:
rectB = m_compass->boundingRect();
rectN = m_compassband->boundingRect();
m_compassband->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_compassband->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
// Last: we just loaded the dial file which is by default valid for a "zero" value
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
// we would end up with an offset when we change a dial file and the needle value
// is not zero at that time.
rollValue = 0;
pitchValue = 0;
headingValue = 0;
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
}
}
else
{ std::cout<<"no file: "<<std::endl; }
}
void PFDGadgetWidget::paint()
{
update();
}
void PFDGadgetWidget::paintEvent(QPaintEvent *event)
{
// Skip painting until the dial file is loaded
if (! m_renderer->isValid()) {
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
return;
}
QGraphicsView::paintEvent(event);
}
// This event enables the dial to be dynamically resized
// whenever the gadget is resized, taking advantage of the vector
// nature of SVG dials.
void PFDGadgetWidget::resizeEvent(QResizeEvent *event)
{
fitInView(m_background, Qt::KeepAspectRatio );
}
// Take an input value and move the elements accordingly.
// Movement is smooth, starts fast and slows down when
// approaching the target.
//
void PFDGadgetWidget::rotateNeedles()
{
int dialCount = 3; // Gets decreased by one for each element
// which has finished moving
double rollDiff;
if ((abs((rollValue-rollTarget)*10) > 5)) {
rollDiff =(rollTarget - rollValue)/5;
} else {
rollDiff = rollTarget - rollValue;
dialCount--;
}
m_world->setRotation(m_world->rotation()+rollDiff);
m_rollscale->setRotation(m_rollscale->rotation()+rollDiff);
rollValue += rollDiff;
double pitchDiff;
if ((abs((pitchValue-pitchTarget)*10) > 5)) {
pitchDiff = (pitchTarget - pitchValue)/5;
} else {
pitchDiff = pitchTarget - pitchValue;
dialCount--;
}
QPointF opd = QPointF(0,pitchDiff);
m_world->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_world->transformOriginPoint();
m_world->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
pitchValue += pitchDiff;
double headingOffset = 0;
double headingDiff;
if ((abs((headingValue-headingTarget)*10) > 5)) {
headingDiff = (headingTarget - headingValue)/5;
} else {
headingDiff = headingTarget-headingValue;
dialCount--;
}
double threshold = -180*compassBandWidth/540;
// Note: rendering can jump oh so very slightly when crossing the 180 degree
// boundary, should not impact actual useability of the display.
if ((headingValue < threshold) && ((headingValue+headingDiff)>=threshold)) {
// We went over 180°: activate a -360 degree offset
headingOffset = 2*threshold;
} else if ((headingValue >= threshold) && ((headingValue+headingDiff)<threshold)) {
// We went under 180°: remove the -360 degree offset
headingOffset = -2*threshold;
}
opd = QPointF(headingDiff+headingOffset,0);
m_compassband->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
headingValue += headingDiff;
//update();
if (!dialCount)
dialTimer.stop();
}
/**
******************************************************************************
*
* @file pfdgadgetwidget.cpp
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdgadgetwidget.h"
#include <iostream>
#include <QDebug>
PFDGadgetWidget::PFDGadgetWidget(QWidget *parent) : QGraphicsView(parent)
{
// TODO: create a proper "needle" object instead of hardcoding all this
// which is ugly (but easy).
setMinimumSize(64,64);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setScene(new QGraphicsScene(this));
setRenderHints(QPainter::Antialiasing);
m_renderer = new QSvgRenderer();
attitudeObj = NULL;
headingObj = NULL;
compassBandWidth = 0;
/*
obj2 = NULL;
obj3 = NULL;
*/
// This timer mechanism makes needles rotate smoothly
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
dialTimer.start(20);
}
PFDGadgetWidget::~PFDGadgetWidget()
{
// Do nothing
}
/*!
\brief Connects the widget to the relevant UAVObjects
We want: AttitudeActual, FlightBattery, Location
*/
void PFDGadgetWidget::connectNeedles() {
if (attitudeObj != NULL)
disconnect(attitudeObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateAttitude(UAVObject*)));
if (headingObj != NULL)
disconnect(headingObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateHeading(UAVObject*)));
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
attitudeObj = dynamic_cast<UAVDataObject*>(objManager->getObject("AttitudeActual"));
if (attitudeObj != NULL ) {
connect(attitudeObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateAttitude(UAVObject*)));
} else {
std::cout << "Error: Object is unknown (AttitudeActual)." << std::endl;
}
headingObj = dynamic_cast<UAVDataObject*>(objManager->getObject("PositionActual"));
if (headingObj != NULL ) {
connect(headingObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateHeading(UAVObject*)));
} else {
std::cout << "Error: Object is unknown (PositionActual)." << std::endl;
}
}
/*!
\brief Reads the updated attitude and computes the new display position
*/
void PFDGadgetWidget::updateAttitude(UAVObject *object1) {
// Double check that the field exists:
QString roll = QString("Roll");
QString pitch = QString("Pitch");
UAVObjectField* field = object1->getField(roll);
UAVObjectField* field2 = object1->getField(pitch);
if (field && field2) {
// These factors assume some things about the PFD SVG, namely:
// - Roll value in degrees
// - Pitch lines are 300px high for a +20/-20 range, which means
// 7.5 pixels per pitch degree.
rollTarget = field->getDouble()*(-1);
pitchTarget = field2->getDouble()*7.5;
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
} else {
std::cout << "UpdateAttitude: Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateHeading(UAVObject *object1) {
// Double check that the field exists:
QString heading = QString("Heading");
UAVObjectField* field = object1->getField(heading);
if (field) {
// These factors assume some things about the PFD SVG, namely:
// - Heading value in degrees
// - Scale is 540 degrees large
headingTarget = field->getDouble()*compassBandWidth/(-540);
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
} else {
std::cout << "UpdateHeading: Wrong field, maybe an issue with object disconnection ?" << std::endl;
}
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateAirspeed(UAVObject *object3) {
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateAltitude(UAVObject *object3) {
}
/*!
\brief Called by the UAVObject which got updated
*/
void PFDGadgetWidget::updateBattery(UAVObject *object3) {
}
/*
Initializes the dial file, and does all the one-time calculations for
display later.
*/
void PFDGadgetWidget::setDialFile(QString dfn)
{
if (QFile::exists(dfn))
{
m_renderer->load(dfn);
if(m_renderer->isValid())
{
/* The PFD element IDs are fixed, not like with the analog dial.
- Background: background
- Foreground: foreground (contains all fixed elements, including plane)
- earth/sky : world
- Roll scale: rollscale
- compass frame: compass (part of the foreground)
- compass band : compass-band
- Home point: homewaypoint
- Next point: nextwaypoint
- Home point bearing: homewaypoint-bearing
- Next point bearing: nextwaypoint-bearing
*/
QGraphicsScene *l_scene = scene();
l_scene->clear(); // Deletes all items contained in the scene as well.
m_background = new QGraphicsSvgItem();
// All other items will be clipped to the shape of the background
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
m_background->setSharedRenderer(m_renderer);
m_background->setElementId("background");
l_scene->addItem(m_background);
m_world = new QGraphicsSvgItem();
m_world->setParentItem(m_background);
m_world->setSharedRenderer(m_renderer);
m_world->setElementId("world");
l_scene->addItem(m_world);
// red Roll scale: rollscale
m_rollscale = new QGraphicsSvgItem();
m_rollscale->setSharedRenderer(m_renderer);
m_rollscale->setElementId("rollscale");
l_scene->addItem(m_rollscale);
// Home point:
m_homewaypoint = new QGraphicsSvgItem();
// Next point:
m_nextwaypoint = new QGraphicsSvgItem();
// Home point bearing:
m_homepointbearing = new QGraphicsSvgItem();
// Next point bearing:
m_nextpointbearing = new QGraphicsSvgItem();
m_foreground = new QGraphicsSvgItem();
m_foreground->setParentItem(m_background);
m_foreground->setSharedRenderer(m_renderer);
m_foreground->setElementId("foreground");
l_scene->addItem(m_foreground);
// Compass:
// Get the default location of the Compass:
QMatrix compassMatrix = m_renderer->matrixForElement("compass");
qreal startX = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).x();
qreal startY = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).y();
// Then once we have the initial location, we can put it
// into a QGraphicsSvgItem which we will display at the same
// place: we do this so that the heading scale can be clipped to
// the compass dial region.
m_compass = new QGraphicsSvgItem();
m_compass->setSharedRenderer(m_renderer);
m_compass->setElementId("compass");
m_compass->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
QGraphicsItem::ItemClipsToShape);
l_scene->addItem(m_compass);
QTransform matrix;
matrix.translate(startX,startY);
m_compass->setTransform(matrix,false);
// Now place the compass scale inside:
m_compassband = new QGraphicsSvgItem();
m_compassband->setSharedRenderer(m_renderer);
m_compassband->setElementId("compass-band");
m_compassband->setParentItem(m_compass);
l_scene->addItem(m_compassband);
matrix.reset();
// Note: the compass band has to be a path, which means all text elements have to be
// converted, ortherwise boundsOnElement does not compute the height correctly
// if the highest element is a text element. This is a Qt Bug as far as I can tell.
// compass-scale is the while bottom line inside the band: using the band's width
// includes half the width of the letters, which causes errors:
compassBandWidth = m_renderer->boundsOnElement("compass-scale").width();
l_scene->setSceneRect(m_background->boundingRect());
// Now Initialize the center for all transforms of the relevant elements to the
// center of the background:
// 1) Move the center of the needle to the center of the background.
QRectF rectB = m_background->boundingRect();
QRectF rectN = m_world->boundingRect();
m_world->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
// 2) Put the transform origin point of the needle at its center.
m_world->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
rectN = m_rollscale->boundingRect();
m_rollscale->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_rollscale->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
// Also to the same init for the compass:
rectB = m_compass->boundingRect();
rectN = m_compassband->boundingRect();
m_compassband->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
m_compassband->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
// Last: we just loaded the dial file which is by default valid for a "zero" value
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
// we would end up with an offset when we change a dial file and the needle value
// is not zero at that time.
rollValue = 0;
pitchValue = 0;
headingValue = 0;
if (!dialTimer.isActive())
dialTimer.start(); // Rearm the dial Timer which might be stopped.
}
}
else
{ std::cout<<"no file: "<<std::endl; }
}
void PFDGadgetWidget::paint()
{
update();
}
void PFDGadgetWidget::paintEvent(QPaintEvent *event)
{
// Skip painting until the dial file is loaded
if (! m_renderer->isValid()) {
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
return;
}
QGraphicsView::paintEvent(event);
}
// This event enables the dial to be dynamically resized
// whenever the gadget is resized, taking advantage of the vector
// nature of SVG dials.
void PFDGadgetWidget::resizeEvent(QResizeEvent *event)
{
fitInView(m_background, Qt::KeepAspectRatio );
}
// Take an input value and move the elements accordingly.
// Movement is smooth, starts fast and slows down when
// approaching the target.
//
void PFDGadgetWidget::rotateNeedles()
{
int dialCount = 3; // Gets decreased by one for each element
// which has finished moving
double rollDiff;
if ((abs((rollValue-rollTarget)*10) > 5)) {
rollDiff =(rollTarget - rollValue)/5;
} else {
rollDiff = rollTarget - rollValue;
dialCount--;
}
m_world->setRotation(m_world->rotation()+rollDiff);
m_rollscale->setRotation(m_rollscale->rotation()+rollDiff);
rollValue += rollDiff;
double pitchDiff;
if ((abs((pitchValue-pitchTarget)*10) > 5)) {
pitchDiff = (pitchTarget - pitchValue)/5;
} else {
pitchDiff = pitchTarget - pitchValue;
dialCount--;
}
QPointF opd = QPointF(0,pitchDiff);
m_world->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
QPointF oop = m_world->transformOriginPoint();
m_world->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
pitchValue += pitchDiff;
double headingOffset = 0;
double headingDiff;
if ((abs((headingValue-headingTarget)*10) > 5)) {
headingDiff = (headingTarget - headingValue)/5;
} else {
headingDiff = headingTarget-headingValue;
dialCount--;
}
double threshold = -180*compassBandWidth/540;
// Note: rendering can jump oh so very slightly when crossing the 180 degree
// boundary, should not impact actual useability of the display.
if ((headingValue < threshold) && ((headingValue+headingDiff)>=threshold)) {
// We went over 180°: activate a -360 degree offset
headingOffset = 2*threshold;
} else if ((headingValue >= threshold) && ((headingValue+headingDiff)<threshold)) {
// We went under 180°: remove the -360 degree offset
headingOffset = -2*threshold;
}
opd = QPointF(headingDiff+headingOffset,0);
m_compassband->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
headingValue += headingDiff;
//update();
if (!dialCount)
dialTimer.stop();
}

View File

@ -1,128 +1,128 @@
/**
******************************************************************************
*
* @file pfdgadgetwidget.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGETWIDGET_H_
#define PFDGADGETWIDGET_H_
#include "pfdgadgetconfiguration.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjects/uavobjectmanager.h"
#include "uavobjects/uavobject.h"
#include <QGraphicsView>
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include <QFile>
#include <QTimer>
class PFDGadgetWidget : public QGraphicsView
{
Q_OBJECT
public:
PFDGadgetWidget(QWidget *parent = 0);
~PFDGadgetWidget();
void setDialFile(QString dfn);
void paint();
void setN2Min(double value) {n2MinValue = value;}
void setN2Max(double value) {n2MaxValue = value;}
void setN2Factor(double value) {n2Factor = value;}
void setN3Min(double value) {n3MinValue = value;}
void setN3Max(double value) {n3MaxValue = value;}
void setN3Factor(double value) {n3Factor = value;}
// Sets up needle/UAVObject connections:
void connectNeedles();
public slots:
void updateAttitude(UAVObject *object1);
void updateHeading(UAVObject *object1);
void updateAirspeed(UAVObject *object1);
void updateAltitude(UAVObject *object1);
void updateBattery(UAVObject *object1);
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
private slots:
void rotateNeedles();
private:
QSvgRenderer *m_renderer;
// Background: background
QGraphicsSvgItem *m_background;
// Foreground: foreground (contains all fixed elements, including plane)
QGraphicsSvgItem *m_foreground;
// earth/sky : world
QGraphicsSvgItem *m_world;
// Roll scale: rollscale
QGraphicsSvgItem *m_rollscale;
// Compass dial:
QGraphicsSvgItem *m_compass;
// Compass band:
QGraphicsSvgItem *m_compassband;
// Home point:
QGraphicsSvgItem *m_homewaypoint;
// Next point:
QGraphicsSvgItem *m_nextwaypoint;
// Home point bearing:
QGraphicsSvgItem *m_homepointbearing;
// Next point bearing:
QGraphicsSvgItem *m_nextpointbearing;
double n1MinValue;
double n1MaxValue;
double n1Factor;
double n2MinValue;
double n2MaxValue;
double n2Factor;
double n3MinValue;
double n3MaxValue;
double n3Factor;
// The Value and target variables
// are expressed in degrees
double rollTarget;
double rollValue;
double pitchTarget;
double pitchValue;
double headingTarget;
double headingValue;
qreal compassBandWidth;
// Name of the fields to read when an update is received:
UAVDataObject* attitudeObj;
UAVDataObject* headingObj;
// Rotation timer
QTimer dialTimer;
};
#endif /* PFDGADGETWIDGET_H_ */
/**
******************************************************************************
*
* @file pfdgadgetwidget.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDGADGETWIDGET_H_
#define PFDGADGETWIDGET_H_
#include "pfdgadgetconfiguration.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjects/uavobjectmanager.h"
#include "uavobjects/uavobject.h"
#include <QGraphicsView>
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include <QFile>
#include <QTimer>
class PFDGadgetWidget : public QGraphicsView
{
Q_OBJECT
public:
PFDGadgetWidget(QWidget *parent = 0);
~PFDGadgetWidget();
void setDialFile(QString dfn);
void paint();
void setN2Min(double value) {n2MinValue = value;}
void setN2Max(double value) {n2MaxValue = value;}
void setN2Factor(double value) {n2Factor = value;}
void setN3Min(double value) {n3MinValue = value;}
void setN3Max(double value) {n3MaxValue = value;}
void setN3Factor(double value) {n3Factor = value;}
// Sets up needle/UAVObject connections:
void connectNeedles();
public slots:
void updateAttitude(UAVObject *object1);
void updateHeading(UAVObject *object1);
void updateAirspeed(UAVObject *object1);
void updateAltitude(UAVObject *object1);
void updateBattery(UAVObject *object1);
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
private slots:
void rotateNeedles();
private:
QSvgRenderer *m_renderer;
// Background: background
QGraphicsSvgItem *m_background;
// Foreground: foreground (contains all fixed elements, including plane)
QGraphicsSvgItem *m_foreground;
// earth/sky : world
QGraphicsSvgItem *m_world;
// Roll scale: rollscale
QGraphicsSvgItem *m_rollscale;
// Compass dial:
QGraphicsSvgItem *m_compass;
// Compass band:
QGraphicsSvgItem *m_compassband;
// Home point:
QGraphicsSvgItem *m_homewaypoint;
// Next point:
QGraphicsSvgItem *m_nextwaypoint;
// Home point bearing:
QGraphicsSvgItem *m_homepointbearing;
// Next point bearing:
QGraphicsSvgItem *m_nextpointbearing;
double n1MinValue;
double n1MaxValue;
double n1Factor;
double n2MinValue;
double n2MaxValue;
double n2Factor;
double n3MinValue;
double n3MaxValue;
double n3Factor;
// The Value and target variables
// are expressed in degrees
double rollTarget;
double rollValue;
double pitchTarget;
double pitchValue;
double headingTarget;
double headingValue;
qreal compassBandWidth;
// Name of the fields to read when an update is received:
UAVDataObject* attitudeObj;
UAVDataObject* headingObj;
// Rotation timer
QTimer dialTimer;
};
#endif /* PFDGADGETWIDGET_H_ */

View File

@ -1,66 +1,66 @@
/**
******************************************************************************
*
* @file pfdplugin.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdplugin.h"
#include "pfdgadgetfactory.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
PFDPlugin::PFDPlugin()
{
// Do nothing
}
PFDPlugin::~PFDPlugin()
{
// Do nothing
}
bool PFDPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
mf = new PFDGadgetFactory(this);
addAutoReleasedObject(mf);
return true;
}
void PFDPlugin::extensionsInitialized()
{
// Do nothing
}
void PFDPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(PFDPlugin)
/**
******************************************************************************
*
* @file pfdplugin.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pfdplugin.h"
#include "pfdgadgetfactory.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
PFDPlugin::PFDPlugin()
{
// Do nothing
}
PFDPlugin::~PFDPlugin()
{
// Do nothing
}
bool PFDPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
mf = new PFDGadgetFactory(this);
addAutoReleasedObject(mf);
return true;
}
void PFDPlugin::extensionsInitialized()
{
// Do nothing
}
void PFDPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(PFDPlugin)

View File

@ -1,47 +1,47 @@
/**
******************************************************************************
*
* @file pfdplugin.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfd
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDPLUGIN_H_
#define PFDPLUGIN_H_
#include <extensionsystem/iplugin.h>
class PFDGadgetFactory;
class PFDPlugin : public ExtensionSystem::IPlugin
{
public:
PFDPlugin();
~PFDPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private:
PFDGadgetFactory *mf;
};
#endif /* PFDPLUGIN_H_ */
/**
******************************************************************************
*
* @file pfdplugin.h
* @author Edouard Lafargue Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup pfdplugin
* @{
*
*****************************************************************************/
/*
* 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 3 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PFDPLUGIN_H_
#define PFDPLUGIN_H_
#include <extensionsystem/iplugin.h>
class PFDGadgetFactory;
class PFDPlugin : public ExtensionSystem::IPlugin
{
public:
PFDPlugin();
~PFDPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private:
PFDGadgetFactory *mf;
};
#endif /* PFDPLUGIN_H_ */