1 /********************************************************************************************** 2 Copyright (C) 2014 Oliver Eichler <oliver.eichler@gmx.de> 3 Copyright (C) 2020 Henri Hornburg <hrnbg@t-online.de> 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 **********************************************************************************************/ 19 20 #ifndef IGISITEM_H 21 #define IGISITEM_H 22 23 #include <QTreeWidgetItem> 24 25 #include <QColor> 26 #include <QCoreApplication> 27 #include <QDateTime> 28 #include <QDomNode> 29 #include <QMap> 30 #include <QMutex> 31 #include <QPainter> 32 #include <QString> 33 #include <QStringList> 34 #include <QUrl> 35 #include <QVariant> 36 37 #include "units/IUnit.h" 38 39 class CGisDraw; 40 class IScrOpt; 41 class IMouse; 42 class QSqlDatabase; 43 class IGisProject; 44 struct searchValue_t; 45 enum searchProperty_e : unsigned int; 46 47 class IGisItem : public QTreeWidgetItem 48 { 49 Q_DECLARE_TR_FUNCTIONS(IGisItem) 50 public: 51 struct history_event_t 52 { 53 QDateTime time; 54 QString hash; 55 QString who = "QMapShack"; 56 QString icon; 57 QString comment; 58 QByteArray data; 59 }; 60 61 struct history_t 62 { history_thistory_t63 history_t() : histIdxInitial(NOIDX), histIdxCurrent(NOIDX) 64 { 65 } 66 resethistory_t67 void reset() 68 { 69 histIdxInitial = NOIDX; 70 histIdxCurrent = NOIDX; 71 events.clear(); 72 } 73 74 qint32 histIdxInitial; 75 qint32 histIdxCurrent; 76 QList<history_event_t> events; 77 }; 78 79 80 struct link_t 81 { 82 QUrl uri; 83 QString text; 84 QString type; 85 }; 86 87 struct wpt_t 88 { wpt_twpt_t89 wpt_t() : 90 lat(NOFLOAT), 91 lon(NOFLOAT), 92 ele(NOINT), 93 magvar(NOINT), 94 geoidheight(NOINT), 95 sat(NOINT), 96 hdop(NOINT), 97 vdop(NOINT), 98 pdop(NOINT), 99 ageofdgpsdata(NOINT), 100 dgpsid(NOINT) 101 { 102 } 103 QPointFwpt_t104 operator QPointF() const 105 { 106 return QPointF(lon, lat); 107 } 108 109 // -- all gpx tags - start 110 qreal lat; 111 qreal lon; 112 qint32 ele; 113 QDateTime time; 114 qint32 magvar; 115 qint32 geoidheight; 116 QString name; 117 QString cmt; 118 QString desc; 119 QString src; 120 QList<link_t> links; 121 QString sym; 122 QString type; 123 QString fix; 124 qint32 sat; 125 qint32 hdop; 126 qint32 vdop; 127 qint32 pdop; 128 qint32 ageofdgpsdata; 129 qint32 dgpsid; 130 // -- all gpx tags - stop 131 QMap<QString, QVariant> extensions; 132 }; 133 134 /// never ever change these numbers. it will break binary data files 135 enum type_e 136 { 137 eTypeWpt = 1 138 , eTypeTrk = 2 139 , eTypeRte = 3 140 , eTypeOvl = 4 141 , eTypeMax = 5 142 }; 143 144 enum mark_e 145 { 146 eMarkNone = 0 147 , eMarkChanged = 0x00000001 148 , eMarkNotPart = 0x00000002 149 , eMarkNotInDB = 0x00000004 150 }; 151 152 enum selection_e 153 { 154 eSelectionNone = 0 155 , eSelectionExact = 0x00000001 156 , eSelectionIntersect = 0x00000002 157 , eSelectionTrk = 0x80000000 158 , eSelectionWpt = 0x40000000 159 , eSelectionRte = 0x20000000 160 , eSelectionOvl = 0x10000000 161 , eSelectionPoi = 0x08000000 162 }; 163 164 using selflags_t = quint32; 165 166 enum color_e 167 { 168 eColorBlack = 0 169 , eColorDarkRed = 1 170 , eColorDarkGreen = 2 171 , eColorDarkYellow = 3 172 , eColorDarkBlue = 4 173 , eColorDarkMagenta = 5 174 , eColorDarkCyan = 6 175 , eColorLightGray = 7 176 , eColorDarkGray = 8 177 , eColorRed = 9 178 , eColorGreen = 10 179 , eColorYellow = 11 180 , eColorBlue = 12 181 , eColorMagenta = 13 182 , eColorCyan = 14 183 , eColorWhite = 15 184 , eColorTransparent = 16 185 }; 186 187 struct key_t 188 { 189 bool operator==(const key_t& k) const 190 { 191 return (item == k.item) && (project == k.project) && (device == k.device); 192 } 193 bool operator!=(const key_t& k) const 194 { 195 return (item != k.item) || (project != k.project) || (device != k.device); 196 } clearkey_t197 void clear() 198 { 199 item.clear(); 200 project.clear(); 201 device.clear(); 202 } 203 QString item; 204 QString project; 205 QString device; 206 }; 207 208 IGisItem(IGisProject* parent, type_e typ, int idx); 209 virtual ~IGisItem(); 210 211 /// this mutex has to be locked when ever the item list is accessed. 212 static QMutex mutexItems; 213 214 static void init(); 215 static QMenu* getColorMenu(const QString& title, QObject* obj, const char* slot, QWidget* parent); 216 static qint32 selectColor(QWidget* parent); 217 218 /** 219 @brief If the item is part of a database project it will update itself with the database content 220 */ 221 virtual void updateFromDB(quint64 id, QSqlDatabase& db); 222 223 /** 224 @brief Update the visual representation of the QTreeWidgetItem 225 @param enable 226 @param disable 227 */ 228 virtual void updateDecoration(quint32 enable, quint32 disable); 229 230 /** 231 @brief Save the item's data into a GPX structure 232 @param gpx the files <gpx> tag to attach the data to 233 */ 234 virtual void save(QDomNode& gpx, bool strictGpx11) = 0; 235 236 /** 237 @brief Get key string to identify object 238 @return 239 */ 240 const key_t& getKey() const; 241 242 /** 243 @brief Get a hash over the items data. 244 245 Every entry in the history has a hash over the item's serialized data. If the 246 data changes a new history entry is created and a new hash calculated. Thus the 247 has can be used to detect if an item has been changed between the last time the 248 hash was read. 249 250 @return The hash as a string reference. 251 */ 252 const QString& getHash(); 253 254 /** 255 @brief Get the hash stored in the database when the item was loaded 256 257 @return The hash as a string 258 */ 259 const QString& getLastDatabaseHash(); 260 261 /** 262 @brief Read the hash stored in the database 263 */ 264 void setLastDatabaseHash(quint64 id, QSqlDatabase& db); 265 266 /** 267 @brief Get the icon attached to object 268 @return 269 */ 270 void setIcon(const QPixmap& icon); 271 getIcon()272 const QPixmap& getIcon() const 273 { 274 return icon; 275 } 276 getDisplayIcon()277 const QPixmap& getDisplayIcon() const 278 { 279 return displayIcon; 280 } 281 /** 282 @brief Get name of this item. 283 @return A reference to the internal string object 284 */ 285 virtual const QString& getName() const = 0; 286 287 /** 288 @brief Get name of this item extended by the project name 289 @return A string object. 290 */ 291 virtual QString getNameEx() const; 292 293 294 enum features_e 295 { 296 eFeatureNone = 0 297 , eFeatureShowName = 0x00000001 298 , eFeatureShowFullText = 0x00000002 299 , eFeatureShowActivity = 0x00000004 300 , eFeatureShowDateTime = 0x00000008 301 , eFeatureShowLinks = 0x00000010 302 }; 303 304 /** 305 @brief Get a short string with the items properties to be displayed in tool tips or similar 306 307 @param showName set true if the first line should be the item's name 308 @param features a combination of features_e types 309 310 @return A string object. 311 */ 312 virtual QString getInfo(quint32 features) const = 0; 313 314 virtual const QString& getComment() const = 0; 315 virtual const QString& getDescription() const = 0; 316 virtual const QList<link_t>& getLinks() const = 0; 317 virtual QDateTime getTimestamp() const = 0; 318 319 320 virtual void setComment(const QString& str) = 0; 321 virtual void setDescription(const QString& str) = 0; 322 virtual void setLinks(const QList<link_t>& links) = 0; 323 324 /** 325 @brief Edit content of item. 326 327 This is quite dependent on the item. The default implementation does nothing. It has to be 328 overwritten and the item has to generate what ever is needed to edit/view it's details. 329 330 */ edit()331 virtual void edit() 332 { 333 } 334 335 /** 336 @brief Get the dimension of the item 337 338 All coordinates are in Rad. Items with no 339 340 @return 341 */ getBoundingRect()342 virtual const QRectF& getBoundingRect() const 343 { 344 return boundingRect; 345 } 346 347 /** 348 @brief Get screen option object to display and handle actions for this item. 349 @param mouse a pointer to the mouse object initiating the action 350 @return A null pointer is returned if no screen option are available 351 */ getScreenOptions(const QPoint & origin,IMouse * mouse)352 virtual IScrOpt* getScreenOptions(const QPoint& origin, IMouse* mouse) 353 { 354 return nullptr; 355 } 356 357 /** 358 @brief Get a point of the item that is close by the given screen pixel coordinate 359 @param point a point in screen pixels 360 @return If no point is found NOPOINTF is returned. 361 */ getPointCloseBy(const QPoint & point)362 virtual QPointF getPointCloseBy(const QPoint& point) 363 { 364 return NOPOINTF; 365 } 366 367 /** 368 @brief Test if the item is close to a given pixel coordinate of the screen 369 370 @param pos the coordinate on the screen in pixel 371 @return If no point can be found NOPOINTF is returned. 372 */ 373 virtual bool isCloseTo(const QPointF& pos) = 0; 374 375 virtual bool isWithin(const QRectF& area, selflags_t mode) = 0; 376 377 /** 378 @brief Receive the current mouse position 379 380 The default does nothing. Override if needed. 381 382 @param pos the mouse position on the screen in pixel 383 */ mouseMove(const QPointF & pos)384 virtual void mouseMove(const QPointF& pos) 385 { 386 Q_UNUSED(pos); 387 } 388 389 /** 390 @brief Query if this item is read only 391 @return True if it is read only. 392 */ 393 bool isReadOnly() const; 394 395 /** 396 @brief Query if the item is imported and was changed 397 @return True if content was changed. 398 */ 399 bool isTainted() const; 400 401 /** 402 @brief Check if item is on a GPS device 403 @return The device type (IDevice::type_e). IDevice::eTypeNone if the item is not stored on a device. 404 */ 405 qint32 isOnDevice() const; 406 407 /** 408 @brief Check if there are any pending unsaved changes 409 @return True if the are changes to be saved 410 */ 411 bool isChanged() const; 412 413 /** 414 @brief Set the read only mode. 415 416 This is quite dependent on the item. The default implementation will display a 417 message box with a warning and ask the user to confirm. 418 419 @param readOnly set true to make item read only 420 421 @return Return true if the mode change has been accepted. 422 */ 423 virtual bool setReadOnlyMode(bool readOnly); 424 425 virtual void drawItem(QPainter& p, const QPolygonF& viewport, QList<QRectF>& blockedAreas, CGisDraw* gis) = 0; drawItem(QPainter & p,const QRectF & viewport,CGisDraw * gis)426 virtual void drawItem(QPainter& p, const QRectF& viewport, CGisDraw* gis) 427 { 428 } 429 virtual void drawLabel(QPainter& p, const QPolygonF& viewport, QList<QRectF>& blockedAreas, const QFontMetricsF& fm, CGisDraw* gis) = 0; 430 virtual void drawHighlight(QPainter& p) = 0; 431 432 virtual void gainUserFocus(bool yes) = 0; 433 434 /** 435 @brief Check for user focus 436 437 @return True if the item has user focus. The default implementation is always false. 438 */ hasUserFocus()439 virtual bool hasUserFocus() const 440 { 441 return false; 442 } 443 444 445 /** 446 @brief Serialize object out of a QDataStream 447 448 See CGisSerialization.cpp for implementation 449 450 @param stream the binary data stream 451 @return The stream object. 452 */ 453 virtual QDataStream& operator<<(QDataStream& stream) = 0; 454 /** 455 @brief Serialize object into a QDataStream 456 457 See CGisSerialization.cpp for implementation 458 459 @param stream the binary data stream 460 @return The stream object. 461 */ 462 virtual QDataStream& operator>>(QDataStream& stream) const = 0; 463 464 /** 465 @brief Get read access to history of changes 466 467 @return A reference to the history structure. 468 */ getHistory()469 const history_t& getHistory() const 470 { 471 return history; 472 } 473 474 /** 475 @brief Load a given state of change from the history 476 @param idx 477 */ 478 void loadHistory(int idx); 479 480 /** 481 @brief Remove all history entries younger than the current selected one. 482 */ 483 void cutHistoryAfter(); 484 485 /** 486 @brief Remove all history entries older than the current selected one. 487 */ 488 void cutHistoryBefore(); 489 490 /** 491 @brief Take data of the most recent entry and apply meta information of first one 492 493 All other entries are lost 494 */ 495 void squashHistory(); 496 497 /** 498 @brief Create a clone of itself and pass back the pointer 499 500 Add the cloned item to the project with the same index as the original 501 502 @return The pointer of the cloned item 503 */ 504 virtual IGisItem* createClone() = 0; 505 506 void setNogo(bool yes); isNogo()507 bool isNogo() const 508 { 509 return bool(flags & eFlagNogo); 510 } 511 512 static const QBrush& getNogoTextureBrush(); 513 514 IGisProject* getParentProject() const; 515 516 /** 517 @brief Remove all HTML tags from a string 518 @param str the string 519 @return A string without HTML tags 520 */ 521 static QString removeHtml(const QString& str); 522 /** 523 @brief Create a HTML formatted text with comment, description and link section. 524 525 Depending on the isReadOnly flag the section headers are links to trigger a function 526 527 @param isReadOnly true if the text should have no active links 528 @param cmt the comment string 529 @param desc the description string 530 @param links a list of links 531 @param key some key to be sent with the header links 532 @return The formatted text ready to be used. 533 */ 534 static QString createText(bool isReadOnly, const QString& cmt, const QString& desc, const QList<link_t>& links, const QString& key = ""); 535 /** 536 @brief Create a HTML formatted text with description and link section. 537 538 Depending on the isReadOnly flag the section headers are links to trigger a function 539 540 @param isReadOnly true if the text should have no active links 541 @param desc the description string 542 @param links a list of links 543 @param key some key to be sent with the header links 544 @return The formatted text ready to be used. 545 */ 546 static QString createText(bool isReadOnly, const QString& desc, const QList<link_t>& links, const QString& key = ""); 547 /** 548 @brief Create a HTML formatted text with a link. 549 550 Depending on the isReadOnly flag the section headers are links to trigger a function 551 552 @param isReadOnly true if the text should have no active links 553 @param href the link address 554 @param str the link's string 555 @param key some key to be sent with the link 556 @return The formated text ready to be used. 557 */ 558 static QString toLink(bool isReadOnly, const QString& href, const QString& str, const QString& key); 559 560 /** 561 @brief Unified handler to get a new item name and a pointer to the traget project 562 563 @param name a reference to a string object with the default name and to receive the name 564 @param project a reference to a IGisProject pointer. On success it will point to the project instance 565 @param itemtype a string to be used for the item type in the dialogs 566 567 568 @return Returns true on success. Otherwise false. 569 */ 570 static bool getNameAndProject(QString& name, IGisProject*& project, const QString& itemtype); 571 572 573 static IGisItem* newGisItem(quint32 type, quint64 id, QSqlDatabase& db, IGisProject* project); 574 575 576 /// a no key value that can be used to nullify references. 577 const static QString noKey; 578 579 const static QString noName; 580 581 struct color_t 582 { 583 const char* name; 584 const QString label; 585 const QColor color; 586 const QString bullet; 587 const QString line; 588 }; 589 getColorMap()590 static const QVector<color_t>& getColorMap() 591 { 592 return colorMap; 593 } 594 595 virtual const searchValue_t getValueByKeyword(searchProperty_e keyword) = 0; 596 597 qreal getRating() const; 598 void setRating(qreal rating); 599 const QSet<QString>& getKeywords() const; 600 QList<QString> getKeywordsSorted() const; 601 void addKeywords(const QSet<QString>& otherKeywords); 602 void removeKeywords(const QSet<QString>& otherKeywords); 603 const QString getRatingKeywordInfo() const; 604 605 protected: 606 /// set icon of QTreeWidgetItem 607 virtual void setSymbol() = 0; 608 /// read waypoint data from an XML snippet 609 void readWpt(const QDomNode& xml, wpt_t& wpt); 610 /// write waypoint data to an XML snippet 611 void writeWpt(QDomElement& xml, const wpt_t& wpt, bool strictGpx11); 612 /// generate a unique key from item's data 613 virtual void genKey() const; 614 /// setup the history structure right after the creation of the item 615 void setupHistory(); 616 /// update current history entry (e.g. to save the flags) 617 virtual void updateHistory(); 618 /// convert a color string from GPX to a QT color 619 QColor str2color(const QString& name); 620 /// convert a QT color to a string to be used in a GPX file 621 QString color2str(const QColor& color); 622 /// to optimize drawing of large polylines split the line into sections that are visible 623 void splitLineToViewport(const QPolygonF& line, const QRectF& extViewport, QList<QPolygonF>& lines); 624 /// call when ever you make a change to the item's data 625 virtual void changed(const QString& what, const QString& icon); 626 627 void loadFromDb(quint64 id, QSqlDatabase& db); 628 bool isVisible(const QRectF& rect, const QPolygonF& viewport, CGisDraw* gis); 629 bool isVisible(const QPointF& point, const QPolygonF& viewport, CGisDraw* gis); 630 bool isWithin(const QRectF& area, selflags_t flags, const QPolygonF& points); 631 void setNogoFlag(bool yes); 632 633 /** 634 @brief Converts a string with HTML tags to a string without HTML depending on the device 635 636 Some devices e.g. Garmin can not handle HTML. 637 638 @param str a string 639 @return A string with HTML removed depending on the device 640 */ 641 QString html2Dev(const QString& str, bool strictGpx11); 642 643 /// see flags_e for possible flags 644 quint32 flags = 0; 645 /// the item's unique key 646 mutable key_t key; 647 /// each item has an icon for the tree widget 648 QPixmap icon; 649 QPixmap displayIcon; 650 /// the dimensions of the item 651 QRectF boundingRect; 652 /// that's where the real data is. An item is completely defined by it's history 653 history_t history; 654 /// the hash in the database when the item was loaded/saved 655 QString lastDatabaseHash; 656 657 enum flags_e 658 { 659 eFlagCreatedInQms = 0x00000001 660 , eFlagWriteAllowed = 0x00000002 661 , eFlagTainted = 0x00000004 662 , eFlagWptBubble = 0x00000100 663 , eFlagNogo = 0x00000200 664 }; 665 666 static QVector<color_t> colorMap; 667 668 /// labeling the GisItems 669 qreal rating = 0; 670 QSet<QString> keywords; 671 private: 672 void showIcon(); 673 }; 674 675 QDataStream& operator>>(QDataStream& stream, IGisItem::history_t& h); 676 QDataStream& operator<<(QDataStream& stream, const IGisItem::history_t& h); 677 678 #endif //IGISITEM_H 679 680