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