...
[jspeed] / src / textelement.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 <QtCore/QString>
20 #include <QtCore/QDebug>
21 #include <QtCore/QTime>
22 #include <QtGui/QGraphicsScene>
23 #include <QtGui/QGraphicsTextItem>
24 #include "textelement.h"
25 #include "reader.h"
26 #include "odometer.h"
27 #include "graphicsscene.h"
28 #include "poialerts.h"
29
30 namespace
31 {
32     const GraphicsElement::AttributeDetails ATTRIBUTES[TextElement::ATTRIBUTE_COUNT] =
33     {
34      {"xpos", true},
35      {"ypos", true},
36      {"zpos", true},
37      {"visiblewhen", false},
38      {"data", false},
39      {"format", false},
40      {"width", true},
41      {"align", false},
42      {"color", false},
43      {"size", true},
44      {"font", false},
45      {"bold", false},
46      {"italic", false},
47      {"uppercase", false},
48      {"letterspacing", true},
49      {"timeformat", false},
50      {"dateformat", false}
51     };
52
53     const QString FIELDS[TextElement::FIELD_COUNT] =  {"TRIP", "TOTAL", "SPEED",
54                                                        "MAXSPEED", "AVGSPEED",
55                                                        "UNIT", "SPEEDUNIT", "TIME", "DATE",
56                                                        "POIDISTANCE", "POITEXT", "ANGLE", "LATITUDE",
57                                                        "LONGITUDE", "ALTITUDE", "DISTANCEUNIT"};
58 }
59
60 TextElement::TextElement(Reader* reader): GraphicsElement(reader),
61 data_(""), format_(""), align_("left"), timeFormat_("hh:mm"),
62 dateFormat_("dd.MM.yyyy"), fontSize_(16), bold_(false), italic_(false),
63 uppercase_(false), letterSpacing_(0)
64 {
65     element_ = new QGraphicsTextItem();
66 }
67
68 bool TextElement::setAttribute(QString const& name, QString const& value)
69 {
70     int intVal = 0;
71     int attrId = -1;
72
73     if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
74     {
75         Attribute attr = static_cast<Attribute>(attrId);
76
77         bool fontChanged = false;
78
79         switch(attr)
80         {
81         case XPOS:
82             element_->setX(intVal);
83             break;
84         case YPOS:
85             element_->setY(intVal);
86             break;
87         case ZPOS:
88             element_->setZValue(intVal);
89             break;
90         case VISIBLEWHEN:
91             setVisibleWhen(strToVisibleWhen(value));
92             break;
93         case DATA:
94             data_ = value;
95             break;
96         case FORMAT:
97             format_ = value;
98             break;
99         case WIDTH:
100             element_->setTextWidth(intVal);
101             break;
102         case ALIGN:
103             align_ = value;
104             break;
105         case COLOR:
106             element_->setDefaultTextColor(QColor(value));
107             break;
108         case SIZE:
109             fontSize_ = intVal;
110             fontChanged = true;
111             break;
112         case FONT:
113             fontFile_ = value;
114             fontChanged = true;
115             break;
116         case BOLD:
117             if(value != "false" && value != "0")
118             {
119                 bold_ = true;
120                 fontChanged = true;
121             }
122             break;
123         case ITALIC:
124             if(value != "false" && value != "0")
125             {
126                 italic_ = true;
127                 fontChanged = true;
128             }
129             break;
130         case UPPERCASE:
131             if(value != "false" && value != "0")
132             {
133                 uppercase_ = true;
134             }
135             break;
136         case LETTERSPACING:
137             letterSpacing_ = intVal;
138             fontChanged = true;
139             break;
140         case TIMEFORMAT:
141             timeFormat_ = value;
142             break;
143         case DATEFORMAT:
144             dateFormat_ = value;
145             break;
146         default:
147             qDebug() << "Unknown attribute: " << attr;
148             return false;
149         }
150
151         if(fontChanged)
152         {
153             return applyFont();
154         }
155
156         return true;
157
158     }
159     else
160     {
161         return false;
162     }
163 }
164
165 bool TextElement::applyFont()
166 {
167     QFont font;
168
169     if(!fontFile_.isEmpty())
170     {
171         if(!getFont(fontFile_, font))
172         {
173             return false;
174         }
175     }
176
177     font.setPointSize(fontSize_);
178
179     if(bold_)
180     {
181         font.setBold(true);
182     }
183
184     if(italic_)
185     {
186         font.setItalic(true);
187     }
188
189     if(letterSpacing_)
190     {
191         font.setLetterSpacing(QFont::PercentageSpacing, letterSpacing_);
192     }
193
194     element_->setFont(font);
195
196     return true;
197 }
198
199 void TextElement::addToScene(GraphicsScene* scene)
200 {
201     specialFields_.clear();
202
203     for(int i = 0; i < FIELD_COUNT; i++)
204     {
205         if(data_.indexOf("{" + FIELDS[i] + "}") != -1)
206         {
207             specialFields_.push_back(static_cast<Field>(i));
208         }
209
210     }
211
212     QString replaced = data_;
213     replaceSpecialFields(replaced);
214     updateHtml(replaced);
215
216     scene->addItem(element_);
217 }
218
219 void TextElement::update()
220 {
221     if(specialFields_.isEmpty())
222     {
223         return;
224     }
225
226     QString replaced = data_;
227     replaceSpecialFields(replaced);
228
229     updateHtml(replaced);
230 }
231
232 void TextElement::updateHtml(QString data)
233 {
234     if(uppercase_)
235     {
236         data = data.toUpper();
237     }
238
239     element_->setHtml("<div align='"+align_+"'>"+data+"</div>");
240 }
241
242 void TextElement::replaceSpecialFields(QString& value)
243 {
244     for(int i = 0; i < specialFields_.size(); i++)
245     {
246         Field f = specialFields_.at(i);
247         Odometer* o = &(Odometer::instance());
248
249         switch(f)
250         {
251         case TRIP:
252             replaceValue(value, f, formatString(o->getTrip()));
253             break;
254         case TOTAL:
255             replaceValue(value, f, formatString(o->getTotal()));
256             break;
257         case SPEED:
258             replaceValue(value, f, formatString(o->getLatestFix().speed));
259             break;
260         case MAXSPEED:
261             replaceValue(value, f, formatString(o->getMaxSpeed()));
262             break;
263         case AVGSPEED:
264             replaceValue(value, f, formatString(o->getAverageSpeed()));
265             break;
266         case UNIT:
267             replaceValue(value, f, o->getUnit());
268             break;
269         case SPEEDUNIT:
270             replaceValue(value, f, o->getSpeedUnit());
271             break;
272         case TIME:
273             replaceValue(value, f, QTime::currentTime().toString(timeFormat_));
274             break;
275         case DATE:
276             replaceValue(value, f, QDate::currentDate().toString(dateFormat_));
277             break;
278         case POIDISTANCE:
279             replaceValue(value, f, handleEmpty(PoiAlerts::instance().getCurrentDistance()));
280             break;
281         case POITEXT:
282             replaceValue(value, f, PoiAlerts::instance().getCurrentPoi());
283             break;
284         case ANGLE:
285             replaceValue(value, f, formatString(o->getLatestFix().track));
286             break;
287         case LATITUDE:
288             replaceValue(value, f, handleEmpty(o->getLatestFix().latitude));
289             break;
290         case LONGITUDE:
291             replaceValue(value, f, handleEmpty(o->getLatestFix().longitude));
292             break;
293         case ALTITUDE:
294             replaceValue(value, f, handleEmpty(o->getLatestFix().altitude));
295             break;
296         case DISTANCEUNIT:
297             replaceValue(value, f, o->getMeterUnit());
298             break;
299         default:
300             qDebug() << "Unknown field: " << f;
301         }
302     }
303 }
304
305 QString TextElement::handleEmpty(double value)
306 {
307     if(value < 0.01)
308     {
309         return "";
310     }
311
312     return formatString(value);
313 }
314
315 void TextElement::replaceValue(QString& value,
316                                TextElement::Field field,
317                                QString const& replace)
318 {
319     value = value.replace("{" + FIELDS[field] + "}", replace);
320 }
321
322 QString TextElement::formatString(double val)
323 {
324     QString format = format_;
325
326     if(format.isEmpty())
327     {
328         format = "%.0lf";
329     }
330
331     QString result;
332     result.sprintf(format.toLatin1().data(), val);
333
334     return result;
335 }
336
337
338 QGraphicsItem* TextElement::getElement() const
339 {
340     return element_;
341 }