1 /********************************************************************************************** 2 Copyright (C) 2014 Oliver Eichler <oliver.eichler@gmx.de> 3 Copyright (C) 2017 Norbert Truchsess <norbert.truchsess@t-online.de> 4 Copyright (C) 2019 Henri Hornburg <hrnbg@t-online.de> 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 **********************************************************************************************/ 20 21 #ifndef CGISITEMWPT_H 22 #define CGISITEMWPT_H 23 24 #include "gis/IGisItem.h" 25 #include "gis/tnv/CTwoNavProject.h" 26 27 #include <QCoreApplication> 28 #include <QPointer> 29 30 struct poi_t; 31 class IGisProject; 32 class QDomNode; 33 class CScrOptWpt; 34 class CScrOptWptRadius; 35 class QSqlDatabase; 36 class CQlgtWpt; 37 class QTextEdit; 38 class QDir; 39 class CFitStream; 40 class CGisItemWpt : public IGisItem 41 { 42 Q_DECLARE_TR_FUNCTIONS(CGisItemWpt) 43 public: 44 enum geocacheservice_e {eGcCom, eOc, eTc, eGcSu, eUnknown=-1}; 45 46 struct geocachelog_t 47 { 48 quint32 id = 0; 49 QDateTime date; 50 QString type; 51 QString finderId; 52 QString finder; 53 bool textIsHtml = false; 54 QString text; 55 }; 56 57 /* 58 * The Date the geocache was hidden is stored in the enclosing wpt's time 59 */ 60 struct geocache_t 61 { 62 geocacheservice_e service = eUnknown; 63 bool hasData = false; 64 quint32 id = 0; 65 bool available = true; 66 bool archived = false; 67 bool needsMaintenance = false; 68 qreal difficulty = 0; 69 qreal terrain = 0; 70 QString name; 71 QString owner; 72 QString ownerId; 73 QString type; 74 QString container; 75 //See ZGeocacheAttributes.txt for meanings. 76 QMap<quint8, bool> attributes; 77 bool shortDescIsHtml = false; 78 QString shortDesc; 79 bool longDescIsHtml = false; 80 QString longDesc; 81 QString hint; 82 QString country; 83 QString state; 84 QString locale; 85 QList<geocachelog_t> logs; 86 87 const static QList<QString> attributeMeanings; 88 static QList<QString> attributeMeaningsTranslated; 89 static QList<QString> initAttributeMeaningsTranslated(); 90 QDateTime getLastFound() const; 91 QString getLogs() const; 92 }; 93 94 struct image_t 95 { 96 QImage pixmap; 97 qreal direction = 0; 98 QString info; 99 QString filePath; 100 QString fileName; 101 }; 102 103 CGisItemWpt(const QPointF& pos, qreal ele, const QDateTime& time, const QString& name, const QString& icon, IGisProject* project); 104 105 /** 106 @brief Create a completely new waypoint 107 @param pos the waypoint's position [°] 108 @param name the waypoint's name 109 @param icon the waypoint's icon 110 @param project the project the waypoint is added to 111 */ 112 CGisItemWpt(const QPointF& pos, const QString& name, const QString& icon, IGisProject* project); 113 /** 114 @brief Create a copy of an existing waypoint with a new position 115 @param pos the waypoint's new position [°] 116 @param parentWpt the waypoint to copy 117 @param project the project the waypoint is added to 118 */ 119 CGisItemWpt(const QPointF& pos, const CGisItemWpt& parentWpt, IGisProject* project); 120 /** 121 @brief Create a 1:1 copy of an existing waypoint (with new key) 122 @param parentWpt the waypoint to copy 123 @param project the project the waypoint is added to 124 @param idx the index to insert the item. If -1 the item will be appended to it's group 125 */ 126 CGisItemWpt(const CGisItemWpt& parentWpt, IGisProject* project, int idx, bool clone); 127 /** 128 @brief Create item from GPX. 129 @param xml the GPX section containing the item 130 @param project the project to append with item 131 */ 132 CGisItemWpt(const QDomNode& xml, IGisProject* project); 133 134 /** 135 @brief Create item from list of changes 136 @param hist the change history 137 @param project the project to append with item 138 */ 139 CGisItemWpt(const history_t& hist, const QString& dbHash, IGisProject* project); 140 141 /** 142 @brief Read item from database by it's database ID 143 @param id the item's ID in the database 144 @param db the database itself 145 @param project the project to append with item 146 */ 147 CGisItemWpt(quint64 id, QSqlDatabase& db, IGisProject* project); 148 149 /** 150 @brief Read item from text stream with TwoNav encoding 151 @param tnvWpt 152 @param project 153 */ 154 CGisItemWpt(const CTwoNavProject::wpt_t& tnvWpt, IGisProject* project); 155 156 CGisItemWpt(const CQlgtWpt& wpt1, IGisProject* project = nullptr); 157 158 CGisItemWpt(CFitStream& stream, IGisProject* project); 159 160 virtual ~CGisItemWpt(); 161 162 IGisItem* createClone() override; 163 164 /** 165 @brief Save waypoint to GPX tree 166 @param gpx The <gpx> node to append by the waypoint 167 */ 168 void save(QDomNode& gpx, bool strictGpx11) override; 169 /** 170 @brief Save waypoint to TwoNav waypoint file 171 @param out the text stream to write to 172 */ 173 void saveTwoNav(QTextStream& out, const QDir& dir); 174 /** 175 @brief Save waypoint to TCX file 176 @param courseNode The course node to append by the waypoint 177 @param crsPtDateTimeToBeSaved course point dateTime to be saved (NOT the waypoint date and time !) 178 */ 179 void saveTCX(QDomNode& courseNode, const QDateTime crsPtDateTimeToBeSaved); 180 /** 181 @brief Read serialized waypoint from a binary data stream 182 @param stream the data stream to read from 183 @return A reference to the stream 184 */ 185 QDataStream& operator<<(QDataStream& stream) override; 186 /** 187 @brief Serialize waypoint into a binary data stream 188 @param stream the data stream to write to. 189 @return A reference to the stream 190 */ 191 QDataStream& operator>>(QDataStream& stream) const override; 192 193 void setName(const QString& str); 194 void setPosition(const QPointF& pos); 195 void setElevation(qint32 val); 196 void setProximity(qreal val); 197 void setIcon(const QString& name); 198 void setComment(const QString& str) override; 199 void setDescription(const QString& str) override; 200 void setLinks(const QList<link_t>& links) override; 201 void setImages(const QList<image_t>& imgs); 202 203 /** 204 @brief Silently append list of links 205 206 Devices uses links to reference multimedia content attached to the waypoint. 207 These links have to be added to the list of normal links. See removeLinksByType() 208 on how to remove these links again. 209 210 @param links list of links. 211 */ appendLinks(const QList<link_t> & links)212 void appendLinks(const QList<link_t>& links) 213 { 214 wpt.links = links + wpt.links; 215 } 216 217 /** 218 @brief Silently append list of images 219 220 This is used to restore images from a device. As these images where part of the waypoint 221 object in the first place they have to be added to the waypoint again without creating 222 a new history entry. 223 224 @param imgs list of images 225 */ appendImages(const QList<image_t> & imgs)226 void appendImages(const QList<image_t>& imgs) 227 { 228 images += imgs; 229 } 230 231 /** 232 @brief Append the list of images by a single image. 233 @param img a single image 234 */ 235 void addImage(const image_t& img); 236 237 getName()238 const QString& getName() const override 239 { 240 return wpt.name.isEmpty() ? noName : wpt.name; 241 } 242 243 QString getInfo(quint32 feature) const override; getPosition()244 QPointF getPosition() const 245 { 246 return QPointF(wpt.lon, wpt.lat); 247 } 248 getElevation()249 qint32 getElevation() const 250 { 251 return wpt.ele; 252 } getProximity()253 qreal getProximity() const 254 { 255 return proximity; 256 } getTime()257 const QDateTime& getTime() const 258 { 259 return wpt.time; 260 } getIconName()261 const QString& getIconName() const 262 { 263 return wpt.sym; 264 } getComment()265 const QString& getComment() const override 266 { 267 return wpt.cmt; 268 } getDescription()269 const QString& getDescription() const override 270 { 271 return wpt.desc; 272 } getGeoCache()273 const geocache_t& getGeoCache() const 274 { 275 return geocache; 276 } getLinks()277 const QList<link_t>& getLinks() const override 278 { 279 return wpt.links; 280 } getImages()281 const QList<image_t>& getImages() const 282 { 283 return images; 284 } 285 getTimestamp()286 QDateTime getTimestamp() const override 287 { 288 return wpt.time; 289 } 290 291 292 IScrOpt* getScreenOptions(const QPoint& origin, IMouse* mouse) override; 293 294 QPointF getPointCloseBy(const QPoint& point) override; 295 296 void drawItem(QPainter& p, const QPolygonF& viewport, QList<QRectF>& blockedAreas, CGisDraw* gis) override; 297 void drawItem(QPainter& p, const QRectF& viewport, CGisDraw* gis) override; 298 void drawLabel(QPainter& p, const QPolygonF& viewport, QList<QRectF>& blockedAreas, const QFontMetricsF& fm, CGisDraw* gis) override; 299 void drawHighlight(QPainter& p) override; 300 bool isCloseTo(const QPointF& pos) override; 301 bool isWithin(const QRectF& area, selflags_t flags) override; 302 void mouseMove(const QPointF& pos) override; 303 void mouseDragged(const QPoint& start, const QPoint& last, const QPoint& pos); 304 void dragFinished(const QPoint& pos); 305 void leftClicked(const QPoint& pos); isGeocache()306 bool isGeocache() 307 { 308 return geocache.hasData; 309 } 310 hasRadius()311 bool hasRadius() 312 { 313 return proximity < NOFLOAT; 314 } 315 getRadius()316 qreal getRadius() 317 { 318 return radius; 319 } 320 321 void gainUserFocus(bool yes) override; 322 323 void edit() override; 324 void editInitial(); 325 326 /** 327 @brief Remove all links from the waypoint's link list with a given type 328 329 This is used by devices that use links to attach multimedia items to a waypoint like images. 330 These links only make sense on the device. Therefor the links have to be removed after the 331 waypoint has been loaded from the device. 332 333 @param type 334 */ 335 void removeLinksByType(const QString& type); 336 337 void toggleBubble(); hasBubble()338 bool hasBubble() 339 { 340 return bool(flags & eFlagWptBubble); 341 } 342 setHideArea(bool hide)343 void setHideArea(bool hide) 344 { 345 hideArea = hide; 346 } 347 348 void genKey() const override; 349 const searchValue_t getValueByKeyword(searchProperty_e keyword) override; 350 351 static QString getLastName(const QString& name); 352 static void newWpt(const QPointF& pt, const QString& name, const QString& desc, IGisProject* project); 353 static void newWpt(const poi_t& poi, IGisProject* project, bool openEditWIndow = true); 354 static bool getIconAndName(QString& icon, QString& name); 355 356 static void drawCircle(QPainter& p, const QPointF& pos, const qreal& r, const bool& avoid, const bool& selected); 357 static qreal calcRadius(const QPointF& posRad, const QPointF& posPx, const qreal& radiusRad, CGisDraw* gis); 358 init()359 static void init() 360 { 361 keywordLambdaMap = initKeywordLambdaMap(); 362 geocache_t::attributeMeaningsTranslated = geocache_t::initAttributeMeaningsTranslated(); 363 } 364 365 private: 366 void setIcon(); 367 void setSymbol() override; 368 void readGpx(const QDomNode& xml); 369 void readTwoNav(const CTwoNavProject::wpt_t& tnvWpt); 370 void readWptFromFit(CFitStream& stream); 371 void readGcExt(const QDomNode& xmlCache); 372 void writeGcExt(QDomNode& xmlCache); 373 void drawBubble(QPainter& p); 374 QPolygonF makePolyline(const QPointF& anchor, const QRectF& r); 375 void processMouseOverBubble(const QPoint& pos); 376 void detBoundingRect(); 377 378 static key_t keyUserFocus; 379 380 // --- start all waypoint data ---- 381 wpt_t wpt; 382 qreal proximity = NOFLOAT; 383 qreal radius = NOFLOAT; 384 bool closeToRadius = false; 385 bool hideArea = false; 386 geocache_t geocache; 387 QList<image_t> images; 388 389 QPointF focus; 390 QPointF posScreen = NOPOINTF; 391 392 // additional data, common to all IGisItems, is found in IItem // 393 394 // --- stop all waypoint data ---- 395 396 QPointer<CScrOptWpt> scrOptWpt; 397 QPointer<CScrOptWptRadius> scrOptRadius; 398 399 bool doSpecialCursor = false; 400 bool doBubbleMove = false; 401 bool doBubbleSize = false; 402 bool mouseIsOverBubble = false; 403 QRect rectBubble; 404 QRect rectBubbleMove {0, 0, 16, 16}; 405 QRect rectBubbleEdit {0, 0, 16, 16}; 406 QRect rectBubbleSize {0, 0, 16, 16}; 407 408 QPoint offsetMouse; 409 QPoint offsetBubble {-320, -150}; 410 quint32 widthBubble = 300; 411 412 using fSearch = std::function<const searchValue_t (CGisItemWpt*)>; 413 static QMap<searchProperty_e, fSearch > keywordLambdaMap; 414 static QMap<searchProperty_e, fSearch > initKeywordLambdaMap(); 415 }; 416 417 #endif // CGISITEMWPT_H 418 419