|
44 | 44 | #endif
|
45 | 45 |
|
46 | 46 |
|
47 |
| -const char* QgsGPXProvider::attr[] = { "Name", "Elevation", "Symbol", "Number", |
48 |
| - "Comment", "Description", "Source", |
49 |
| - "URL", "URL name" }; |
| 47 | +const char* QgsGPXProvider::attr[] = { "name", "elevation", "symbol", "number", |
| 48 | + "comment", "description", "source", |
| 49 | + "url", "url name" }; |
50 | 50 |
|
51 | 51 |
|
52 | 52 | QgsGPXProvider::QgsGPXProvider(QString uri) : mDataSourceUri(uri),
|
@@ -78,7 +78,7 @@ QgsGPXProvider::QgsGPXProvider(QString uri) : mDataSourceUri(uri),
|
78 | 78 | else if (mFeatureType == RouteType || mFeatureType == TrackType) {
|
79 | 79 | mGeomType = 2;
|
80 | 80 | for (int i = 0; i < 8; ++i)
|
81 |
| - mAllAttributes.push_back(7); |
| 81 | + mAllAttributes.push_back(i); |
82 | 82 | attributeFields.push_back(QgsField(attr[NumAttr], "text"));
|
83 | 83 | }
|
84 | 84 | attributeFields.push_back(QgsField(attr[CmtAttr], "text"));
|
@@ -532,17 +532,173 @@ bool QgsGPXProvider::isValid(){
|
532 | 532 |
|
533 | 533 |
|
534 | 534 | bool QgsGPXProvider::addFeatures(std::list<QgsFeature*> flist) {
|
| 535 | + |
| 536 | + // add all the features |
535 | 537 | for (std::list<QgsFeature*>::const_iterator iter = flist.begin();
|
536 | 538 | iter != flist.end(); ++iter) {
|
537 | 539 | if (!addFeature(*iter))
|
538 | 540 | return false;
|
539 | 541 | }
|
| 542 | + |
| 543 | + // write back to file |
| 544 | + QDomDocument qdd; |
| 545 | + data->fillDom(qdd); |
| 546 | + QFile file(mFileName); |
| 547 | + if (!file.open(IO_WriteOnly)) |
| 548 | + return false; |
| 549 | + QTextStream ostr(&file); |
| 550 | + ostr<<qdd.toString(); |
540 | 551 | return true;
|
541 | 552 | }
|
542 | 553 |
|
543 | 554 |
|
544 | 555 | bool QgsGPXProvider::addFeature(QgsFeature* f) {
|
545 |
| - return false; |
| 556 | + unsigned char* geo = f->getGeometry(); |
| 557 | + int featureId; |
| 558 | + bool success = false; |
| 559 | + GPSObject* obj = NULL; |
| 560 | + const std::vector<QgsFeatureAttribute>& attrs(f->attributeMap()); |
| 561 | + |
| 562 | + // is it a waypoint? |
| 563 | + if (mFeatureType == WaypointType && geo != NULL && geo[1] == 1) { |
| 564 | + |
| 565 | + // add geometry |
| 566 | + Waypoint wpt; |
| 567 | + std::memcpy(&wpt.lon, geo+5, sizeof(double)); |
| 568 | + std::memcpy(&wpt.lat, geo+13, sizeof(double)); |
| 569 | + |
| 570 | + // add waypoint-specific attributes |
| 571 | + for (int i = 0; i < attrs.size(); ++i) { |
| 572 | + if (attrs[i].fieldName() == attr[EleAttr]) { |
| 573 | + bool eleIsOK; |
| 574 | + double ele = attrs[i].fieldValue().toDouble(&eleIsOK); |
| 575 | + if (eleIsOK) |
| 576 | + wpt.ele = ele; |
| 577 | + } |
| 578 | + else if (attrs[i].fieldName() == attr[SymAttr]) { |
| 579 | + wpt.sym = attrs[i].fieldValue(); |
| 580 | + } |
| 581 | + } |
| 582 | + |
| 583 | + featureId = data->addWaypoint(wpt); |
| 584 | + success = true; |
| 585 | + obj = &(data->getWaypoint(featureId)); |
| 586 | + } |
| 587 | + |
| 588 | + // is it a route? |
| 589 | + if (mFeatureType == RouteType && geo != NULL && geo[1] == 2) { |
| 590 | + |
| 591 | + Route rte; |
| 592 | + |
| 593 | + // reset bounds |
| 594 | + rte.xMin = std::numeric_limits<double>::max(); |
| 595 | + rte.xMax = -std::numeric_limits<double>::max(); |
| 596 | + rte.yMin = std::numeric_limits<double>::max(); |
| 597 | + rte.yMax = -std::numeric_limits<double>::max(); |
| 598 | + |
| 599 | + // add geometry |
| 600 | + int nPoints; |
| 601 | + std::memcpy(&nPoints, geo + 5, 4); |
| 602 | + for (int i = 0; i < nPoints; ++i) { |
| 603 | + double lat, lon; |
| 604 | + std::memcpy(&lon, geo + 9 + 16 * i, sizeof(double)); |
| 605 | + std::memcpy(&lat, geo + 9 + 16 * i + 8, sizeof(double)); |
| 606 | + Routepoint rtept; |
| 607 | + rtept.lat = lat; |
| 608 | + rtept.lon = lon; |
| 609 | + rte.points.push_back(rtept); |
| 610 | + rte.xMin = rte.xMin < lon ? rte.xMin : lon; |
| 611 | + rte.xMax = rte.xMax > lon ? rte.xMax : lon; |
| 612 | + rte.yMin = rte.yMin < lat ? rte.yMin : lat; |
| 613 | + rte.yMax = rte.yMax > lat ? rte.yMax : lat; |
| 614 | + } |
| 615 | + |
| 616 | + // add route-specific attributes |
| 617 | + for (int i = 0; i < attrs.size(); ++i) { |
| 618 | + if (attrs[i].fieldName() == attr[NumAttr]) { |
| 619 | + bool numIsOK; |
| 620 | + long num = attrs[i].fieldValue().toLong(&numIsOK); |
| 621 | + if (numIsOK) |
| 622 | + rte.number = num; |
| 623 | + } |
| 624 | + } |
| 625 | + |
| 626 | + featureId = data->addRoute(rte); |
| 627 | + success = true; |
| 628 | + obj = &(data->getRoute(featureId)); |
| 629 | + } |
| 630 | + |
| 631 | + // is it a track? |
| 632 | + if (mFeatureType == TrackType && geo != NULL && geo[1] == 2) { |
| 633 | + |
| 634 | + Track trk; |
| 635 | + TrackSegment trkseg; |
| 636 | + |
| 637 | + // reset bounds |
| 638 | + trk.xMin = std::numeric_limits<double>::max(); |
| 639 | + trk.xMax = -std::numeric_limits<double>::max(); |
| 640 | + trk.yMin = std::numeric_limits<double>::max(); |
| 641 | + trk.yMax = -std::numeric_limits<double>::max(); |
| 642 | + |
| 643 | + // add geometry |
| 644 | + int nPoints; |
| 645 | + std::memcpy(&nPoints, geo + 5, 4); |
| 646 | + for (int i = 0; i < nPoints; ++i) { |
| 647 | + double lat, lon; |
| 648 | + std::memcpy(&lon, geo + 9 + 16 * i, sizeof(double)); |
| 649 | + std::memcpy(&lat, geo + 9 + 16 * i + 8, sizeof(double)); |
| 650 | + Trackpoint trkpt; |
| 651 | + trkpt.lat = lat; |
| 652 | + trkpt.lon = lon; |
| 653 | + trkseg.points.push_back(trkpt); |
| 654 | + trk.xMin = trk.xMin < lon ? trk.xMin : lon; |
| 655 | + trk.xMax = trk.xMax > lon ? trk.xMax : lon; |
| 656 | + trk.yMin = trk.yMin < lat ? trk.yMin : lat; |
| 657 | + trk.yMax = trk.yMax > lat ? trk.yMax : lat; |
| 658 | + } |
| 659 | + |
| 660 | + // add track-specific attributes |
| 661 | + for (int i = 0; i < attrs.size(); ++i) { |
| 662 | + if (attrs[i].fieldName() == attr[NumAttr]) { |
| 663 | + bool numIsOK; |
| 664 | + long num = attrs[i].fieldValue().toLong(&numIsOK); |
| 665 | + if (numIsOK) |
| 666 | + trk.number = num; |
| 667 | + } |
| 668 | + } |
| 669 | + |
| 670 | + trk.segments.push_back(trkseg); |
| 671 | + featureId = data->addTrack(trk); |
| 672 | + success = true; |
| 673 | + obj = &(data->getTrack(featureId)); |
| 674 | + } |
| 675 | + |
| 676 | + |
| 677 | + // add common attributes |
| 678 | + if (obj) { |
| 679 | + for (int i = 0; i < attrs.size(); ++i) { |
| 680 | + if (attrs[i].fieldName() == attr[NameAttr]) { |
| 681 | + obj->name = attrs[i].fieldValue(); |
| 682 | + } |
| 683 | + else if (attrs[i].fieldName() == attr[CmtAttr]) { |
| 684 | + obj->cmt = attrs[i].fieldValue(); |
| 685 | + } |
| 686 | + else if (attrs[i].fieldName() == attr[DscAttr]) { |
| 687 | + obj->desc = attrs[i].fieldValue(); |
| 688 | + } |
| 689 | + else if (attrs[i].fieldName() == attr[SrcAttr]) { |
| 690 | + obj->src = attrs[i].fieldValue(); |
| 691 | + } |
| 692 | + else if (attrs[i].fieldName() == attr[URLAttr]) { |
| 693 | + obj->url = attrs[i].fieldValue(); |
| 694 | + } |
| 695 | + else if (attrs[i].fieldName() == attr[URLNameAttr]) { |
| 696 | + obj->urlname = attrs[i].fieldValue(); |
| 697 | + } |
| 698 | + } |
| 699 | + } |
| 700 | + |
| 701 | + return success; |
546 | 702 | }
|
547 | 703 |
|
548 | 704 |
|
|
0 commit comments