/*
* This file is part of jSpeed.
*
* jSpeed 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.
*
* jSpeed 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 jSpeed. If not, see .
*
*/
#include
#include
#include
#include
#include "compass.h"
#include "reader.h"
#include "graphicsscene.h"
#include "odometer.h"
namespace
{
const GraphicsElement::AttributeDetails ATTRIBUTES[Compass::ATTRIBUTE_COUNT] =
{
{"xpos", true},
{"ypos", true},
{"zpos", true},
{"visiblewhen", false},
{"src", false},
{"xrotationpoint", true},
{"yrotationpoint", true}
};
int const ANIMATION_TIME = 700;
int const ANIMATION_FRAMES = 80;
int const ANIMATION_UPDATEINTERVAL = 20;
double const COMPASS_IGNORE_THRESHOLD = 90.0;
}
Compass::Compass(Reader* reader, bool animate): GraphicsElement(reader),
xRotationPoint_(-1), yRotationPoint_(-1), x_(0), y_(0), targetAngle_(0),
startAngle_(0), angle_(-1), width_(0), height_(0), imageSet_(false), animate_(animate), timer_(0)
{
element_ = new QGraphicsPixmapItem();
if(animate_)
{
timer_ = new QTimeLine(ANIMATION_TIME);
timer_->setFrameRange(0, ANIMATION_FRAMES);
timer_->setUpdateInterval(ANIMATION_UPDATEINTERVAL);
connect(timer_, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
}
}
Compass::~Compass()
{
delete timer_;
}
bool Compass::setAttribute(QString const& name, QString const& value)
{
int intVal = 0;
int attrId = -1;
if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
{
Attribute attr = static_cast(attrId);
switch(attr)
{
case XPOS:
x_ = intVal;
break;
case YPOS:
y_ = intVal;
break;
case ZPOS:
element_->setZValue(intVal);
break;
case VISIBLEWHEN:
setVisibleWhen(strToVisibleWhen(value));
break;
case SRC:
return loadImage(value);
break;
case XROTATIONPOINT:
xRotationPoint_ = intVal;
break;
case YROTATIONPOINT:
yRotationPoint_ = intVal;
break;
default:
qDebug() << "Unknown attribute: " << attr;
return false;
}
return true;
}
else
{
return false;
}
}
void Compass::addToScene(GraphicsScene* scene)
{
if(!imageSet_)
{
return;
}
if(xRotationPoint_ < 0)
{
xRotationPoint_ = width_ / 2;
}
if(yRotationPoint_ < 0)
{
yRotationPoint_ = height_ / 2;
}
element_->setTransformOriginPoint(xRotationPoint_, yRotationPoint_);
element_->setX(x_ - xRotationPoint_);
element_->setY(y_ - yRotationPoint_);
bool animateVal = animate_;
animate_ = false;
update();
animate_ = animateVal;
scene->addItem(element_);
}
void Compass::update()
{
if(Odometer::instance().getLatestFix().epd > COMPASS_IGNORE_THRESHOLD)
{
return;
}
double angle = Odometer::instance().getLatestFix().track * -1.0;
if(angle < -180)
{
angle += 360.0;
}
int rounded = static_cast(round(angle));
if(rounded == angle_)
{
return;
}
angle_ = rounded;
if(!animate_)
{
element_->setRotation(rounded);
}
else
{
targetAngle_ = rounded;
startAngle_ = element_->rotation();
if(timer_->state() == QTimeLine::Running)
{
timer_->stop();
}
timer_->start();
}
}
void Compass::setFrame(int frame)
{
element_->setRotation(startAngle_ + ((static_cast(frame) / ANIMATION_FRAMES) * (targetAngle_ - startAngle_)));
}
bool Compass::loadImage(QString const& name)
{
QPixmap pixmap;
QByteArray data;
if(!readFile(name, data))
{
return false;
}
if(!pixmap.loadFromData(data))
{
setError("Invalid image file: " + name);
return false;
}
width_ = pixmap.width();
height_ = pixmap.height();
element_->setPixmap(pixmap);
imageSet_ = true;
return true;
}
QGraphicsItem* Compass::getElement() const
{
return element_;
}