1 /**********************************************************************************************
2 Copyright (C) 2014 Oliver Eichler <oliver.eichler@gmx.de>
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
16
17 **********************************************************************************************/
18
19 #include "CQlgtWpt.h"
20 #include "helpers/CWptIconManager.h"
21
22 struct wpt_head_entry_t
23 {
wpt_head_entry_twpt_head_entry_t24 wpt_head_entry_t() : type(CQlgtWpt::eEnd), offset(0)
25 {
26 }
27 qint32 type;
28 quint32 offset;
29 QByteArray data;
30 };
31
32
operator >>(QDataStream & s,CQlgtWpt & wpt)33 QDataStream& operator >>(QDataStream& s, CQlgtWpt& wpt)
34 {
35 QIODevice* dev = s.device();
36 qint64 pos = dev->pos();
37
38 char magic[9];
39 s.readRawData(magic, 9);
40
41 if(strncmp(magic, "QLWpt ", 9))
42 {
43 dev->seek(pos);
44 // throw(tr("This is not waypoint data."));
45 return s;
46 }
47
48 QList<wpt_head_entry_t> entries;
49
50 while(1)
51 {
52 wpt_head_entry_t entry;
53 s >> entry.type >> entry.offset;
54 entries << entry;
55 if(entry.type == CQlgtWpt::eEnd)
56 {
57 break;
58 }
59 }
60
61 QList<wpt_head_entry_t>::iterator entry = entries.begin();
62 while(entry != entries.end())
63 {
64 qint64 o = pos + entry->offset;
65 dev->seek(o);
66 s >> entry->data;
67
68 switch(entry->type)
69 {
70 case CQlgtWpt::eBase:
71 {
72 QString icon;
73
74 QDataStream s1(&entry->data, QIODevice::ReadOnly);
75 s1.setVersion(QDataStream::Qt_4_5);
76
77 s1 >> wpt.key;
78 s1 >> wpt.sticky;
79 s1 >> wpt.timestamp;
80 s1 >> icon;
81 s1 >> wpt.name;
82 s1 >> wpt.comment;
83 s1 >> wpt.lat;
84 s1 >> wpt.lon;
85 s1 >> wpt.ele;
86 s1 >> wpt.prx;
87 s1 >> wpt.link;
88 s1 >> wpt.description;
89 s1 >> wpt.urlname;
90 s1 >> wpt.type;
91 s1 >> wpt.parentWpt;
92 s1 >> wpt.selected;
93
94 if(!s1.atEnd())
95 {
96 s1 >> wpt.dir;
97 }
98 else
99 {
100 wpt.dir = WPT_NOFLOAT;
101 }
102
103 wpt.setIcon(icon);
104 break;
105 }
106
107 case CQlgtWpt::eImage:
108 {
109 QDataStream s1(&entry->data, QIODevice::ReadOnly);
110 s1.setVersion(QDataStream::Qt_4_5);
111 CQlgtWpt::image_t img;
112
113 wpt.images.clear();
114
115 s1 >> img.offset;
116 while(img.offset)
117 {
118 wpt.images << img;
119 s1 >> img.offset;
120 }
121
122 QList<CQlgtWpt::image_t>::iterator image = wpt.images.begin();
123 while(image != wpt.images.end())
124 {
125 s1.device()->seek(image->offset);
126 s1 >> image->filePath;
127 s1 >> image->info;
128 s1 >> image->pixmap;
129 ++image;
130 }
131 break;
132 }
133
134 case CQlgtWpt::eGeoCache:
135 {
136 quint32 N, n;
137 QDataStream s1(&entry->data, QIODevice::ReadOnly);
138 s1.setVersion(QDataStream::Qt_4_5);
139 wpt.geocache = CQlgtWpt::geocache_t();
140 CQlgtWpt::geocache_t& cache = wpt.geocache;
141
142 s1 >> (quint8&)cache.service;
143 s1 >> cache.hasData;
144 s1 >> cache.id;
145 s1 >> cache.available;
146 s1 >> cache.archived;
147 s1 >> cache.difficulty;
148 s1 >> cache.terrain;
149 s1 >> cache.status;
150 s1 >> cache.name;
151 s1 >> cache.owner;
152 s1 >> cache.ownerId;
153 s1 >> cache.type;
154 s1 >> cache.container;
155 s1 >> cache.shortDesc;
156 s1 >> cache.longDesc;
157 s1 >> cache.hint;
158 s1 >> cache.country;
159 s1 >> cache.state;
160 s1 >> cache.locale;
161
162 s1 >> N;
163
164 for(n = 0; n < N; n++)
165 {
166 CQlgtWpt::geocachelog_t log;
167
168 s1 >> log.id;
169 s1 >> log.date;
170 s1 >> log.type;
171 s1 >> log.finderId;
172 s1 >> log.finder;
173 s1 >> log.text;
174
175 cache.logs << log;
176 }
177
178 s1 >> cache.exportBuddies;
179
180 cache.hasData = true;
181
182 break;
183 }
184
185 default:
186 ;
187 }
188
189 ++entry;
190 }
191
192 return s;
193 }
194
operator <<(QDataStream & s,CQlgtWpt & wpt)195 QDataStream& operator <<(QDataStream& s, CQlgtWpt& wpt)
196 {
197 QList<wpt_head_entry_t> entries;
198
199 //---------------------------------------
200 // prepare base data
201 //---------------------------------------
202 wpt_head_entry_t entryBase;
203 entryBase.type = CQlgtWpt::eBase;
204 QDataStream s1(&entryBase.data, QIODevice::WriteOnly);
205 s1.setVersion(QDataStream::Qt_4_5);
206
207 s1 << wpt.key;
208 s1 << wpt.sticky;
209 s1 << wpt.timestamp;
210 s1 << wpt.iconString;
211 s1 << wpt.name;
212 s1 << wpt.comment;
213 s1 << wpt.lat;
214 s1 << wpt.lon;
215 s1 << wpt.ele;
216 s1 << wpt.prx;
217 s1 << wpt.link;
218 s1 << wpt.description;
219 s1 << wpt.urlname;
220 s1 << wpt.type;
221 s1 << QString();
222 s1 << wpt.selected;
223 s1 << wpt.dir;
224
225 entries << entryBase;
226
227 //---------------------------------------
228 // prepare image data
229 //---------------------------------------
230 wpt_head_entry_t entryImage;
231 entryImage.type = CQlgtWpt::eImage;
232 QDataStream s2(&entryImage.data, QIODevice::WriteOnly);
233 s2.setVersion(QDataStream::Qt_4_5);
234
235 // write place holder for image offset
236 QList<CQlgtWpt::image_t>::iterator image = wpt.images.begin();
237 while(image != wpt.images.end())
238 {
239 s2 << (quint32)0;
240 ++image;
241 }
242 // offset terminator
243 s2 << (quint32)0;
244
245 // write image data and store the actual offset
246 image = wpt.images.begin();
247 while(image != wpt.images.end())
248 {
249 image->offset = (quint32)s2.device()->pos();
250 s2 << image->filePath;
251 s2 << image->info;
252 s2 << image->pixmap;
253 ++image;
254 }
255
256 // finally write image offset table
257 s2.device()->seek(0);
258 image = wpt.images.begin();
259 while(image != wpt.images.end())
260 {
261 s2 << image->offset;
262 ++image;
263 }
264
265 entries << entryImage;
266
267 //---------------------------------------
268 // prepare geocache data
269 //---------------------------------------
270 if(wpt.geocache.hasData)
271 {
272 wpt_head_entry_t entryGeoCache;
273 entryGeoCache.type = CQlgtWpt::eGeoCache;
274 QDataStream s3(&entryGeoCache.data, QIODevice::WriteOnly);
275 s3.setVersion(QDataStream::Qt_4_5);
276
277 CQlgtWpt::geocache_t& cache = wpt.geocache;
278
279 s3 << (quint8)cache.service;
280 s3 << cache.hasData;
281 s3 << cache.id;
282 s3 << cache.available;
283 s3 << cache.archived;
284 s3 << cache.difficulty;
285 s3 << cache.terrain;
286 s3 << cache.status;
287 s3 << cache.name;
288 s3 << cache.owner;
289 s3 << cache.ownerId;
290 s3 << cache.type;
291 s3 << cache.container;
292 s3 << cache.shortDesc;
293 s3 << cache.longDesc;
294 s3 << cache.hint;
295 s3 << cache.country;
296 s3 << cache.state;
297 s3 << cache.locale;
298
299 s3 << cache.logs.count();
300
301 for(const CQlgtWpt::geocachelog_t& log : qAsConst(cache.logs))
302 {
303 s3 << log.id;
304 s3 << log.date;
305 s3 << log.type;
306 s3 << log.finderId;
307 s3 << log.finder;
308 s3 << log.text;
309 }
310
311 s3 << cache.exportBuddies;
312
313 entries << entryGeoCache;
314 }
315 //---------------------------------------
316 // prepare terminator
317 //---------------------------------------
318 wpt_head_entry_t entryEnd;
319 entryEnd.type = CQlgtWpt::eEnd;
320 entries << entryEnd;
321
322 //---------------------------------------
323 //---------------------------------------
324 // now start to actually write data;
325 //---------------------------------------
326 //---------------------------------------
327 // write magic key
328 s.writeRawData("QLWpt ", 9);
329
330 // calculate offset table
331 quint32 offset = entries.count() * 8 + 9;
332
333 QList<wpt_head_entry_t>::iterator entry = entries.begin();
334 while(entry != entries.end())
335 {
336 entry->offset = offset;
337 offset += entry->data.size() + sizeof(quint32);
338 ++entry;
339 }
340
341 // write offset table
342 entry = entries.begin();
343 while(entry != entries.end())
344 {
345 s << entry->type << entry->offset;
346 ++entry;
347 }
348
349 // write entry data
350 entry = entries.begin();
351 while(entry != entries.end())
352 {
353 s << entry->data;
354 ++entry;
355 }
356
357 return s;
358 }
359
360
CQlgtWpt(quint64 id,QObject * parent)361 CQlgtWpt::CQlgtWpt(quint64 id, QObject* parent)
362 : QObject(parent)
363 , IItem(id)
364 {
365 }
366
~CQlgtWpt()367 CQlgtWpt::~CQlgtWpt()
368 {
369 }
370
setIcon(const QString & str)371 void CQlgtWpt::setIcon(const QString& str)
372 {
373 QPointF focus;
374 iconString = str;
375 iconPixmap = CWptIconManager::self().getWptIconByName(str, focus);
376 }
377