487 lines
17 KiB
C++
487 lines
17 KiB
C++
/**
|
|
******************************************************************************
|
|
*
|
|
* @file waypointitem.cpp
|
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
|
* @brief A graphicsItem representing a WayPoint
|
|
* @see The GNU Public License (GPL) Version 3
|
|
* @defgroup OPMapWidget
|
|
* @{
|
|
*
|
|
*****************************************************************************/
|
|
/*
|
|
* 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 "waypointitem.h"
|
|
#include "homeitem.h"
|
|
#include <QGraphicsSceneMouseEvent>
|
|
|
|
namespace mapcontrol {
|
|
WayPointItem::WayPointItem(const internals::PointLatLng &coord, int const & altitude, MapGraphicItem *map, wptype type) : coord(coord), reached(false), description(""), shownumber(true), isDragging(false), altitude(altitude), map(map), myType(type)
|
|
{
|
|
text = 0;
|
|
numberI = 0;
|
|
isMagic = false;
|
|
picture.load(QString::fromUtf8(":/markers/images/marker.png"));
|
|
number = WayPointItem::snumber;
|
|
++WayPointItem::snumber;
|
|
this->setFlag(QGraphicsItem::ItemIsMovable, true);
|
|
this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
|
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|
SetShowNumber(shownumber);
|
|
RefreshToolTip();
|
|
RefreshPos();
|
|
myHome = NULL;
|
|
QList<QGraphicsItem *> list = map->childItems();
|
|
foreach(QGraphicsItem * obj, list) {
|
|
HomeItem *h = qgraphicsitem_cast <HomeItem *>(obj);
|
|
|
|
if (h) {
|
|
myHome = h;
|
|
}
|
|
}
|
|
|
|
if (myHome) {
|
|
map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing);
|
|
relativeCoord.altitudeRelative = Altitude() - myHome->Altitude();
|
|
connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float)));
|
|
}
|
|
connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *)));
|
|
emit manualCoordChange(this);
|
|
connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos()));
|
|
connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal)));
|
|
}
|
|
|
|
WayPointItem::WayPointItem(MapGraphicItem *map, bool magicwaypoint) : reached(false), description(""), shownumber(true), isDragging(false), altitude(0), map(map)
|
|
{
|
|
relativeCoord.bearing = 0;
|
|
relativeCoord.distance = 0;
|
|
relativeCoord.altitudeRelative = 0;
|
|
myType = relative;
|
|
if (magicwaypoint) {
|
|
isMagic = true;
|
|
picture.load(QString::fromUtf8(":/opmap/images/waypoint_marker3.png"));
|
|
number = -1;
|
|
} else {
|
|
isMagic = false;
|
|
number = WayPointItem::snumber;
|
|
++WayPointItem::snumber;
|
|
}
|
|
text = 0;
|
|
numberI = 0;
|
|
this->setFlag(QGraphicsItem::ItemIsMovable, true);
|
|
this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
|
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|
SetShowNumber(shownumber);
|
|
RefreshToolTip();
|
|
RefreshPos();
|
|
myHome = NULL;
|
|
QList<QGraphicsItem *> list = map->childItems();
|
|
foreach(QGraphicsItem * obj, list) {
|
|
HomeItem *h = qgraphicsitem_cast <HomeItem *>(obj);
|
|
|
|
if (h) {
|
|
myHome = h;
|
|
}
|
|
}
|
|
|
|
if (myHome) {
|
|
coord = map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing);
|
|
SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative);
|
|
connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float)));
|
|
}
|
|
connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *)));
|
|
emit manualCoordChange(this);
|
|
connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos()));
|
|
connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal)));
|
|
}
|
|
WayPointItem::WayPointItem(const internals::PointLatLng &coord, int const & altitude, const QString &description, MapGraphicItem *map, wptype type) : coord(coord), reached(false), description(description), shownumber(true), isDragging(false), altitude(altitude), map(map), myType(type)
|
|
{
|
|
text = 0;
|
|
numberI = 0;
|
|
isMagic = false;
|
|
picture.load(QString::fromUtf8(":/markers/images/marker.png"));
|
|
number = WayPointItem::snumber;
|
|
++WayPointItem::snumber;
|
|
this->setFlag(QGraphicsItem::ItemIsMovable, true);
|
|
this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
|
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|
SetShowNumber(shownumber);
|
|
RefreshToolTip();
|
|
RefreshPos();
|
|
myHome = NULL;
|
|
QList<QGraphicsItem *> list = map->childItems();
|
|
foreach(QGraphicsItem * obj, list) {
|
|
HomeItem *h = qgraphicsitem_cast <HomeItem *>(obj);
|
|
|
|
if (h) {
|
|
myHome = h;
|
|
}
|
|
}
|
|
if (myHome) {
|
|
map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing);
|
|
relativeCoord.altitudeRelative = Altitude() - myHome->Altitude();
|
|
connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float)));
|
|
}
|
|
connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *)));
|
|
emit manualCoordChange(this);
|
|
connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos()));
|
|
connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal)));
|
|
}
|
|
|
|
WayPointItem::WayPointItem(const distBearingAltitude &relativeCoordenate, const QString &description, MapGraphicItem *map) : relativeCoord(relativeCoordenate), reached(false), description(description), shownumber(true), isDragging(false), map(map)
|
|
{
|
|
myHome = NULL;
|
|
QList<QGraphicsItem *> list = map->childItems();
|
|
foreach(QGraphicsItem * obj, list) {
|
|
HomeItem *h = qgraphicsitem_cast <HomeItem *>(obj);
|
|
|
|
if (h) {
|
|
myHome = h;
|
|
}
|
|
}
|
|
if (myHome) {
|
|
connect(myHome, SIGNAL(homePositionChanged(internals::PointLatLng, float)), this, SLOT(onHomePositionChanged(internals::PointLatLng, float)));
|
|
coord = map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing);
|
|
SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative);
|
|
}
|
|
myType = relative;
|
|
text = 0;
|
|
numberI = 0;
|
|
isMagic = false;
|
|
picture.load(QString::fromUtf8(":/markers/images/marker.png"));
|
|
number = WayPointItem::snumber;
|
|
++WayPointItem::snumber;
|
|
this->setFlag(QGraphicsItem::ItemIsMovable, true);
|
|
this->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
|
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|
SetShowNumber(shownumber);
|
|
RefreshToolTip();
|
|
RefreshPos();
|
|
connect(this, SIGNAL(waypointdoubleclick(WayPointItem *)), map, SIGNAL(wpdoubleclicked(WayPointItem *)));
|
|
emit manualCoordChange(this);
|
|
connect(map, SIGNAL(childRefreshPosition()), this, SLOT(RefreshPos()));
|
|
connect(map, SIGNAL(childSetOpacity(qreal)), this, SLOT(setOpacitySlot(qreal)));
|
|
}
|
|
|
|
void WayPointItem::setWPType(wptype type)
|
|
{
|
|
myType = type;
|
|
emit WPValuesChanged(this);
|
|
RefreshPos();
|
|
RefreshToolTip();
|
|
this->update();
|
|
}
|
|
|
|
QRectF WayPointItem::boundingRect() const
|
|
{
|
|
return QRectF(-picture.width() / 2, -picture.height(), picture.width(), picture.height());
|
|
}
|
|
void WayPointItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
Q_UNUSED(option);
|
|
Q_UNUSED(widget);
|
|
painter->drawPixmap(-picture.width() / 2, -picture.height(), picture);
|
|
painter->setPen(Qt::green);
|
|
if (this->isSelected()) {
|
|
painter->drawRect(QRectF(-picture.width() / 2, -picture.height(), picture.width() - 1, picture.height() - 1));
|
|
}
|
|
}
|
|
void WayPointItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (event->button() == Qt::LeftButton) {
|
|
emit waypointdoubleclick(this);
|
|
}
|
|
}
|
|
|
|
void WayPointItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (event->button() == Qt::LeftButton) {
|
|
text = new QGraphicsSimpleTextItem(this);
|
|
textBG = new QGraphicsRectItem(this);
|
|
|
|
textBG->setBrush(Qt::white);
|
|
|
|
text->setPen(QPen(Qt::black));
|
|
text->setPos(10, -picture.height());
|
|
textBG->setPos(10, -picture.height());
|
|
text->setZValue(3);
|
|
RefreshToolTip();
|
|
isDragging = true;
|
|
}
|
|
QGraphicsItem::mousePressEvent(event);
|
|
}
|
|
void WayPointItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (event->button() == Qt::LeftButton) {
|
|
if (text) {
|
|
delete text;
|
|
text = NULL;
|
|
}
|
|
if (textBG) {
|
|
delete textBG;
|
|
textBG = NULL;
|
|
}
|
|
|
|
isDragging = false;
|
|
RefreshToolTip();
|
|
|
|
|
|
emit manualCoordChange(this);
|
|
emit localPositionChanged(this->pos(), this);
|
|
emit WPValuesChanged(this);
|
|
|
|
coord = map->FromLocalToLatLng(this->pos().x(), this->pos().y());
|
|
emit WPChanged(this->Number(),Coord().Lat(),Coord().Lng());
|
|
}
|
|
QGraphicsItem::mouseReleaseEvent(event);
|
|
}
|
|
void WayPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if (isDragging) {
|
|
coord = map->FromLocalToLatLng(this->pos().x(), this->pos().y());
|
|
QString coord_str = " " + QString::number(coord.Lat(), 'f', 6) + " " + QString::number(coord.Lng(), 'f', 6);
|
|
if (myHome) {
|
|
map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing);
|
|
}
|
|
QString relativeCoord_str =QString::number(relativeCoord.distance) + "m " + QString::number(relativeCoord.bearing * 180 / M_PI) + "deg";
|
|
text->setText(coord_str + "\n" + relativeCoord_str);
|
|
textBG->setRect(text->boundingRect());
|
|
emit localPositionChanged(this->pos(), this);
|
|
emit WPValuesChanged(this);
|
|
}
|
|
QGraphicsItem::mouseMoveEvent(event);
|
|
}
|
|
void WayPointItem::SetAltitude(const float &value)
|
|
{
|
|
if (altitude == value) {
|
|
return;
|
|
}
|
|
altitude = value;
|
|
if (myHome) {
|
|
relativeCoord.altitudeRelative = altitude - myHome->Altitude();
|
|
}
|
|
RefreshToolTip();
|
|
emit WPValuesChanged(this);
|
|
this->update();
|
|
}
|
|
|
|
void WayPointItem::setRelativeCoord(distBearingAltitude value)
|
|
{
|
|
if (qAbs(value.distance - relativeCoord.distance) < 0.1
|
|
&& qAbs(value.bearing - relativeCoord.bearing) < 0.01 && value.altitudeRelative == relativeCoord.altitudeRelative) {
|
|
return;
|
|
}
|
|
relativeCoord = value;
|
|
if (myHome) {
|
|
SetCoord(map->Projection()->translate(myHome->Coord(), relativeCoord.distance, relativeCoord.bearing));
|
|
SetAltitude(myHome->Altitude() + relativeCoord.altitudeRelative);
|
|
}
|
|
RefreshPos();
|
|
RefreshToolTip();
|
|
emit WPValuesChanged(this);
|
|
this->update();
|
|
}
|
|
|
|
void WayPointItem::SetCoord(const internals::PointLatLng &value)
|
|
{
|
|
if (qAbs(Coord().Lat() - value.Lat()) < 0.0001 && qAbs(Coord().Lng() - value.Lng()) < 0.0001) {
|
|
return;
|
|
}
|
|
coord = value;
|
|
distBearingAltitude back = relativeCoord;
|
|
if (myHome) {
|
|
map->Projection()->offSetFromLatLngs(myHome->Coord(), Coord(), back.distance, back.bearing);
|
|
}
|
|
if (qAbs(back.bearing - relativeCoord.bearing) > 0.01 || qAbs(back.distance - relativeCoord.distance) > 0.1) {
|
|
relativeCoord = back;
|
|
}
|
|
emit WPValuesChanged(this);
|
|
RefreshPos();
|
|
RefreshToolTip();
|
|
this->update();
|
|
}
|
|
void WayPointItem::SetDescription(const QString &value)
|
|
{
|
|
if (description == value) {
|
|
return;
|
|
}
|
|
description = value;
|
|
RefreshToolTip();
|
|
emit WPValuesChanged(this);
|
|
this->update();
|
|
}
|
|
void WayPointItem::SetNumber(const int &value)
|
|
{
|
|
int oldnumber = number;
|
|
|
|
number = value;
|
|
RefreshToolTip();
|
|
numberI->setText(QString::number(numberAdjusted()));
|
|
numberIBG->setRect(numberI->boundingRect().adjusted(-2, 0, 1, 0));
|
|
this->update();
|
|
emit WPNumberChanged(oldnumber, value, this);
|
|
}
|
|
void WayPointItem::SetReached(const bool &value)
|
|
{
|
|
reached = value;
|
|
emit WPValuesChanged(this);
|
|
if (value) {
|
|
picture.load(QString::fromUtf8(":/markers/images/bigMarkerGreen.png"));
|
|
} else {
|
|
if (!isMagic) {
|
|
if ((this->flags() & QGraphicsItem::ItemIsMovable) == QGraphicsItem::ItemIsMovable) {
|
|
picture.load(QString::fromUtf8(":/markers/images/marker.png"));
|
|
} else {
|
|
picture.load(QString::fromUtf8(":/markers/images/waypoint_marker2.png"));
|
|
}
|
|
} else {
|
|
picture.load(QString::fromUtf8(":/opmap/images/waypoint_marker3.png"));
|
|
}
|
|
}
|
|
this->update();
|
|
}
|
|
void WayPointItem::SetShowNumber(const bool &value)
|
|
{
|
|
shownumber = value;
|
|
if ((numberI == 0) && value) {
|
|
numberI = new QGraphicsSimpleTextItem(this);
|
|
numberIBG = new QGraphicsRectItem(this);
|
|
numberIBG->setBrush(Qt::white);
|
|
numberIBG->setOpacity(0.5);
|
|
numberI->setZValue(3);
|
|
numberI->setPen(QPen(Qt::blue));
|
|
numberI->setPos(0, -13 - picture.height());
|
|
numberIBG->setPos(0, -13 - picture.height());
|
|
numberI->setText(QString::number(numberAdjusted()));
|
|
numberIBG->setRect(numberI->boundingRect().adjusted(-2, 0, 1, 0));
|
|
} else if (!value && numberI) {
|
|
delete numberI;
|
|
delete numberIBG;
|
|
}
|
|
this->update();
|
|
}
|
|
void WayPointItem::WPDeleted(const int &onumber, WayPointItem *waypoint)
|
|
{
|
|
Q_UNUSED(waypoint);
|
|
int n = number;
|
|
if (number > onumber) {
|
|
SetNumber(--n);
|
|
}
|
|
}
|
|
void WayPointItem::WPInserted(const int &onumber, WayPointItem *waypoint)
|
|
{
|
|
if (Number() == -1) {
|
|
return;
|
|
}
|
|
|
|
if (waypoint != this) {
|
|
if (onumber <= number) {
|
|
SetNumber(++number);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WayPointItem::onHomePositionChanged(internals::PointLatLng homepos, float homeAltitude)
|
|
{
|
|
if (myType == relative) {
|
|
coord = map->Projection()->translate(homepos, relativeCoord.distance, relativeCoord.bearing);
|
|
SetAltitude(relativeCoord.altitudeRelative + homeAltitude);
|
|
emit WPValuesChanged(this);
|
|
RefreshPos();
|
|
RefreshToolTip();
|
|
this->update();
|
|
} else {
|
|
if (myHome) {
|
|
map->Projection()->offSetFromLatLngs(myHome->Coord(), coord, relativeCoord.distance, relativeCoord.bearing);
|
|
relativeCoord.altitudeRelative = Altitude() - homeAltitude;
|
|
}
|
|
emit WPValuesChanged(this);
|
|
}
|
|
}
|
|
|
|
void WayPointItem::WPRenumbered(const int &oldnumber, const int &newnumber, WayPointItem *waypoint)
|
|
{
|
|
if (waypoint != this) {
|
|
if (((oldnumber > number) && (newnumber <= number))) {
|
|
SetNumber(++number);
|
|
} else if (((oldnumber < number) && (newnumber > number))) {
|
|
SetNumber(--number);
|
|
} else if (newnumber == number) {
|
|
SetNumber(++number);
|
|
}
|
|
}
|
|
}
|
|
int WayPointItem::type() const
|
|
{
|
|
// Enable the use of qgraphicsitem_cast with this item.
|
|
return Type;
|
|
}
|
|
|
|
WayPointItem::~WayPointItem()
|
|
{
|
|
emit aboutToBeDeleted(this);
|
|
|
|
--WayPointItem::snumber;
|
|
}
|
|
void WayPointItem::RefreshPos()
|
|
{
|
|
core::Point point = map->FromLatLngToLocal(coord);
|
|
|
|
this->setPos(point.X(), point.Y());
|
|
emit localPositionChanged(this->pos(), this);
|
|
}
|
|
|
|
void WayPointItem::setOpacitySlot(qreal opacity)
|
|
{
|
|
setOpacity(opacity);
|
|
}
|
|
void WayPointItem::RefreshToolTip()
|
|
{
|
|
QString type_str;
|
|
|
|
if (myType == relative) {
|
|
type_str = "Relative";
|
|
} else {
|
|
type_str = "Absolute";
|
|
}
|
|
QString coord_str = " " + QString::number(coord.Lat(), 'f', 6) + " " + QString::number(coord.Lng(), 'f', 6);
|
|
QString relativeCoord_str = " Distance:" + QString::number(relativeCoord.distance) + " Bearing:" + QString::number(relativeCoord.bearing * 180 / M_PI);
|
|
QString relativeAltitude_str = QString::number(relativeCoord.altitudeRelative);
|
|
if (Number() != -1) {
|
|
setToolTip(QString("WayPoint Number:%1\nDescription:%2\nCoordinate:%4\nFrom Home:%5\nRelative altitude:%6\nAltitude:%7\nType:%8\n%9").arg(QString::number(numberAdjusted())).arg(description).arg(coord_str).arg(relativeCoord_str).arg(relativeAltitude_str).arg(QString::number(altitude)).arg(type_str).arg(myCustomString));
|
|
} else {
|
|
setToolTip(QString("Magic WayPoint\nCoordinate:%1\nFrom Home:%2\nAltitude:%3\nType:%4\n%5").arg(coord_str).arg(relativeCoord_str).arg(QString::number(altitude)).arg(type_str).arg(myCustomString));
|
|
}
|
|
}
|
|
|
|
void WayPointItem::setFlag(QGraphicsItem::GraphicsItemFlag flag, bool enabled)
|
|
{
|
|
if (isMagic) {
|
|
QGraphicsItem::setFlag(flag, enabled);
|
|
return;
|
|
} else if (flag == QGraphicsItem::ItemIsMovable) {
|
|
if (enabled) {
|
|
picture.load(QString::fromUtf8(":/markers/images/marker.png"));
|
|
} else {
|
|
picture.load(QString::fromUtf8(":/markers/images/waypoint_marker2.png"));
|
|
}
|
|
}
|
|
QGraphicsItem::setFlag(flag, enabled);
|
|
}
|
|
|
|
int WayPointItem::snumber = 0;
|
|
}
|