Added POI text field. Some tuning to detail screen item position.
[jspeed] / src / pointer.cpp
1 /*
2  * This file is part of jSpeed.
3  *
4  * jSpeed is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * jSpeed is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QtGui/QGraphicsPixmapItem>
20 #include <QtCore/QDebug>
21 #include <QtCore/QTimeLine>
22 #include <math.h>
23 #include "pointer.h"
24 #include "reader.h"
25 #include "graphicsscene.h"
26 #include "odometer.h"
27
28 namespace
29 {
30     const GraphicsElement::AttributeDetails ATTRIBUTES[Pointer::ATTRIBUTE_COUNT] =
31     {
32      {"xpos", true},
33      {"ypos", true},
34      {"zpos", true},
35      {"visiblewhen", false},
36      {"src", false},
37      {"zeroangle", true},
38      {"fullangle", true},
39      {"zerospeed", true},
40      {"fullspeed", true},
41      {"xrotationpoint", true},
42      {"yrotationpoint", true}
43     };
44
45     int const ANIMATION_TIME = 500;
46     int const ANIMATION_FRAMES = 50;
47     int const ANIMATION_UPDATEINTERVAL = 20;
48 }
49
50 Pointer::Pointer(Reader* reader, bool animate): GraphicsElement(reader),
51 xRotationPoint_(0), yRotationPoint_(0), x_(0), y_(0), zeroAngle_(0),
52 fullAngle_(180), zeroSpeed_(0), fullSpeed_(220), targetAngle_(0),
53 startAngle_(0), angle_(-1), imageSet_(false), animate_(animate), timer_(0)
54 {
55     element_ = new QGraphicsPixmapItem();
56
57     if(animate_)
58     {
59         timer_ = new QTimeLine(ANIMATION_TIME);
60         timer_->setFrameRange(0, ANIMATION_FRAMES);
61         timer_->setUpdateInterval(ANIMATION_UPDATEINTERVAL);
62         connect(timer_, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
63     }
64
65 }
66
67 Pointer::~Pointer()
68 {
69     delete timer_;
70 }
71
72 bool Pointer::setAttribute(QString const& name, QString const& value)
73 {
74     int intVal = 0;
75     int attrId = -1;
76
77     if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
78     {
79         Attribute attr = static_cast<Attribute>(attrId);
80
81         switch(attr)
82         {
83         case XPOS:
84             x_ = intVal;
85             break;
86         case YPOS:
87             y_ = intVal;
88             break;
89         case ZPOS:
90             element_->setZValue(intVal);
91             break;
92         case VISIBLEWHEN:
93             setVisibleWhen(strToVisibleWhen(value));
94             break;
95         case SRC:
96             return loadImage(value);
97             break;
98         case ZEROANGLE:
99             zeroAngle_ = intVal;
100             break;
101         case FULLANGLE:
102             fullAngle_ = intVal;
103             break;
104         case ZEROSPEED:
105             zeroSpeed_ = intVal;
106             break;
107         case FULLSPEED:
108             fullSpeed_ = intVal;
109             break;
110         case XROTATIONPOINT:
111             xRotationPoint_ = intVal;
112             break;
113         case YROTATIONPOINT:
114             yRotationPoint_ = intVal;
115             break;
116         default:
117             qDebug() << "Unknown attribute: " << attr;
118             return false;
119         }
120
121         return true;
122     }
123     else
124     {
125         return false;
126     }
127 }
128
129 void Pointer::addToScene(GraphicsScene* scene)
130 {
131     if(!imageSet_)
132     {
133         return;
134     }
135
136     element_->setTransformOriginPoint(xRotationPoint_, yRotationPoint_);
137     element_->setX(x_ - xRotationPoint_);
138     element_->setY(y_ - yRotationPoint_);
139
140     bool animateVal = animate_;
141     animate_ = false;
142     update();
143     animate_ = animateVal;
144
145     scene->addItem(element_);
146 }
147
148 void Pointer::update()
149 {
150     double speed = Odometer::instance().getLatestFix().kmSpeed;
151
152     if(speed < zeroSpeed_)
153     {
154         speed = static_cast<double>(zeroSpeed_);
155     }
156     else if(speed > fullSpeed_)
157     {
158         speed = static_cast<double>(fullSpeed_);
159     }
160
161     double multiplier = static_cast<double>(speed - zeroSpeed_) / (fullSpeed_ - zeroSpeed_);
162     double angle = static_cast<double>(zeroAngle_) + ((fullAngle_ - zeroAngle_) * multiplier);
163
164     int rounded = static_cast<int>(round(angle));
165
166     if(rounded == angle_)
167     {
168         return;
169     }
170
171     angle_ = rounded;
172
173     if(!animate_)
174     {
175         element_->setRotation(rounded);
176     }
177     else
178     {
179         targetAngle_ = rounded;
180         startAngle_ = element_->rotation();
181
182         if(timer_->state() == QTimeLine::Running)
183         {
184             timer_->stop();
185         }
186
187         timer_->start();
188     }
189 }
190
191 void Pointer::setFrame(int frame)
192 {
193     element_->setRotation(startAngle_ + ((static_cast<double>(frame) / ANIMATION_FRAMES) * (targetAngle_ - startAngle_)));
194 }
195
196 bool Pointer::loadImage(QString const& name)
197 {
198     QPixmap pixmap;
199     QByteArray data;
200
201     if(!readFile(name, data))
202     {
203         return false;
204     }
205
206     if(!pixmap.loadFromData(data))
207     {
208         setError("Invalid image file: " + name);
209         return false;
210     }
211
212     element_->setPixmap(pixmap);
213     imageSet_ = true;
214
215     return true;
216 }
217
218 QGraphicsItem* Pointer::getElement() const
219 {
220     return element_;
221 }
222