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