static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) { uint32_t uuid; degrees_t latitude = parse_degrees(line, &line); degrees_t longitude = parse_degrees(line, &line); struct dive *dive = _dive; struct dive_site *ds = get_dive_site_for_dive(dive); if (!ds) { uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL); if (!uuid) uuid = create_dive_site_with_gps("", latitude, longitude, dive->when); dive->dive_site_uuid = uuid; } else { if (dive_site_has_gps_location(ds) && (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { const char *coords = printGPSCoords(latitude.udeg, longitude.udeg); // we have a dive site that already has GPS coordinates ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords); free((void *)coords); } ds->latitude = latitude; ds->longitude = longitude; } }
QGeoCoordinate MapWidgetHelper::getCoordinatesForUUID(QVariant dive_site_uuid) { const uint32_t uuid = qvariant_cast<uint32_t>(dive_site_uuid); struct dive_site *ds = get_dive_site_by_uuid(uuid); if (!ds || !dive_site_has_gps_location(ds)) return QGeoCoordinate(0.0, 0.0); return QGeoCoordinate(ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001); }
void MapWidget::centerOnIndex(const QModelIndex& idx) { CHECK_IS_READY_RETURN_VOID(); dive_site *ds = idx.model()->index(idx.row(), LocationInformationModel::DIVESITE).data().value<dive_site *>(); if (!ds || ds == RECENTLY_ADDED_DIVESITE || !dive_site_has_gps_location(ds)) m_mapHelper->centerOnSelectedDiveSite(); else centerOnDiveSite(ds); }
// we don't overwrite any existing GPS info in the dive // so get the dive site and if there is none or there is one without GPS fix, add it static void copy_gps_location(struct dive *from, struct dive *to) { struct dive_site *ds = get_dive_site_for_dive(to); if (!ds || !dive_site_has_gps_location(ds)) { struct dive_site *gds = get_dive_site_for_dive(from); if (!ds) { // simply link to the one created for the fake dive to->dive_site_uuid = gds->uuid; } else { ds->latitude = gds->latitude; ds->longitude = gds->longitude; if (same_string(ds->name, "")) ds->name = copy_string(gds->name); } } }
/* find the closest one, no more than distance meters away - if more than one at same distance, pick the first */ uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longitude, int distance, struct dive_site **dsp) { int i; int uuid = 0; struct dive_site *ds; unsigned int cur_distance, min_distance = distance; for_each_dive_site (i, ds) { if (dive_site_has_gps_location(ds) && (cur_distance = get_distance(ds->latitude, ds->longitude, latitude, longitude)) < min_distance) { min_distance = cur_distance; uuid = ds->uuid; if (dsp) *dsp = ds; } } return uuid; }
void writeMarkers(struct membuffer *b, const bool selected_only) { int i, dive_no = 0; struct dive *dive; char pre[1000], post[1000]; for_each_dive (i, dive) { if (selected_only) { if (!dive->selected) continue; } struct dive_site *ds = get_dive_site_for_dive(dive); if (!ds || !dive_site_has_gps_location(ds)) continue; put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); put_degrees(b, ds->longitude, ",", ")});\n"); put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">"); snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:")); put_HTML_date(b, dive, pre, "</p>"); snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Time:")); put_HTML_time(b, dive, pre, "</p>"); snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Duration:")); snprintf(post, sizeof(post), " %s</p>", translate("gettextFromC", "min")); put_duration(b, dive->duration, pre, post); put_string(b, "<p> "); put_HTML_quoted(b, translate("gettextFromC", "Max. depth:")); put_HTML_depth(b, dive, " ", "</p>"); put_string(b, "<p> "); put_HTML_quoted(b, translate("gettextFromC", "Air temp.:")); put_HTML_airtemp(b, dive, " ", "</p>"); put_string(b, "<p> "); put_HTML_quoted(b, translate("gettextFromC", "Water temp.:")); put_HTML_watertemp(b, dive, " ", "</p>"); snprintf(pre, sizeof(pre), "<p>%s <b>", translate("gettextFromC", "Location:")); put_string(b, pre); put_HTML_quoted(b, get_dive_location(dive)); put_string(b, "</b></p>"); snprintf(pre, sizeof(pre), "<p> %s ", translate("gettextFromC", "Notes:")); put_HTML_notes(b, dive, pre, " </p>"); put_string(b, "</p>'+'</div>'+'</div>'});\ninfowindows.push(tempinfowindow);\n"); put_format(b, "google.maps.event.addListener(markers[%d], 'mouseover', function() {\ninfowindows[%d].open(map,markers[%d]);}", dive_no, dive_no, dive_no); put_format(b, ");google.maps.event.addListener(markers[%d], 'mouseout', function() {\ninfowindows[%d].close();});\n", dive_no, dive_no); dive_no++; } }
void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &origIdx) const { QFont fontBigger = qApp->font(); QFont fontSmaller = qApp->font(); QFontMetrics fmBigger(fontBigger); QStyleOptionViewItemV4 opt = option; const QAbstractProxyModel *proxyModel = dynamic_cast<const QAbstractProxyModel*>(origIdx.model()); QModelIndex index = proxyModel->mapToSource(origIdx); QStyledItemDelegate::initStyleOption(&opt, index); QString diveSiteName = index.data().toString(); QString bottomText; QIcon icon = index.data(Qt::DecorationRole).value<QIcon>(); struct dive_site *ds = get_dive_site_by_uuid( index.model()->data(index.model()->index(index.row(),0)).toInt() ); //Special case: do not show name, but instead, show if (index.row() < 2) { diveSiteName = index.data().toString(); bottomText = index.data(Qt::ToolTipRole).toString(); goto print_part; } if (!ds) return; for (int i = 0; i < 3; i++) { if (prefs.geocoding.category[i] == TC_NONE) continue; int idx = taxonomy_index_for_category(&ds->taxonomy, prefs.geocoding.category[i]); if (idx == -1) continue; if(!bottomText.isEmpty()) bottomText += " / "; bottomText += QString(ds->taxonomy.category[idx].value); } if (bottomText.isEmpty()) { const char *gpsCoords = printGPSCoords(ds->latitude.udeg, ds->longitude.udeg); bottomText = QString(gpsCoords); free( (void*) gpsCoords); } if (dive_site_has_gps_location(ds) && dive_site_has_gps_location(&displayed_dive_site)) { // so we are showing a completion and both the current dive site and the completion // have a GPS fix... so let's show the distance if (ds->latitude.udeg == displayed_dive_site.latitude.udeg && ds->longitude.udeg == displayed_dive_site.longitude.udeg) { bottomText += tr(" (same GPS fix)"); } else { int distanceMeters = get_distance(ds->latitude, ds->longitude, displayed_dive_site.latitude, displayed_dive_site.longitude); QString distance = distance_string(distanceMeters); int nr = nr_of_dives_at_dive_site(ds->uuid, false); bottomText += tr(" (~%1 away").arg(distance); bottomText += tr(", %1 dive(s) here)").arg(nr); } } if (bottomText.isEmpty()) { if (dive_site_has_gps_location(&displayed_dive_site)) bottomText = tr("(no existing GPS data, add GPS fix from this dive)"); else bottomText = tr("(no GPS data)"); } bottomText = tr("Pick site: ") + bottomText; print_part: fontBigger.setPointSize(fontBigger.pointSize() + 1); fontBigger.setBold(true); QPen textPen = QPen(option.state & QStyle::State_Selected ? option.palette.highlightedText().color() : option.palette.text().color(), 1); initStyleOption(&opt, index); opt.text = QString(); opt.icon = QIcon(); painter->setClipRect(option.rect); painter->save(); if (option.state & QStyle::State_Selected) { painter->setPen(QPen(opt.palette.highlight().color().darker())); painter->setBrush(opt.palette.highlight()); const qreal pad = 1.0; const qreal pad2 = pad * 2.0; const qreal rounding = 5.0; painter->drawRoundedRect(option.rect.x() + pad, option.rect.y() + pad, option.rect.width() - pad2, option.rect.height() - pad2, rounding, rounding); } painter->setPen(textPen); painter->setFont(fontBigger); const qreal textPad = 5.0; painter->drawText(option.rect.x() + textPad, option.rect.y() + fmBigger.boundingRect("YH").height(), diveSiteName); double pointSize = fontSmaller.pointSizeF(); fontSmaller.setPointSizeF(0.9 * pointSize); painter->setFont(fontSmaller); painter->drawText(option.rect.x() + textPad, option.rect.y() + fmBigger.boundingRect("YH").height() * 2, bottomText); painter->restore(); if (!icon.isNull()) { painter->save(); painter->drawPixmap( option.rect.x() + option.rect.width() - 24, option.rect.y() + option.rect.height() - 24, icon.pixmap(20,20)); painter->restore(); } }
void MapWidgetHelper::centerOnDiveSite(struct dive_site *ds) { QVector<struct dive_site *> selDS; QVector<QGeoCoordinate> selGC; QGeoCoordinate dsCoord; // selection of multiple dives is only possible on the desktop. // in the case of the mobile version only handle the passed dive_site. #ifndef SUBSURFACE_MOBILE int idx; struct dive *dive; for_each_dive (idx, dive) { struct dive_site *dss = get_dive_site_for_dive(dive); if (!dive_site_has_gps_location(dss) || !dive->selected) continue; // only store dive sites with GPS selDS.append(dss); selGC.append(QGeoCoordinate(dss->latitude.udeg * 0.000001, dss->longitude.udeg * 0.000001)); } #else if (dive_site_has_gps_location(ds)) { selDS.append(ds); selGC.append(QGeoCoordinate(ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001)); } #endif if (!dive_site_has_gps_location(ds) && !selDS.size()) { // only a single dive site with no GPS selected m_mapLocationModel->setSelectedUuid(ds ? ds->uuid : 0, false); QMetaObject::invokeMethod(m_map, "deselectMapLocation"); } else if (selDS.size() == 1) { // a single dive site with GPS selected ds = selDS.at(0); m_mapLocationModel->setSelectedUuid(ds->uuid, false); dsCoord.setLatitude(ds->latitude.udeg * 0.000001); dsCoord.setLongitude(ds->longitude.udeg * 0.000001); QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(dsCoord))); } else if (selDS.size() > 1) { /* more than one dive sites with GPS selected. * find the most top-left and bottom-right dive sites on the map coordinate system. */ ds = selDS.at(0); m_mapLocationModel->setSelectedUuid(ds->uuid, false); qreal minLat = 0.0, minLon = 0.0, maxLat = 0.0, maxLon = 0.0; bool start = true; foreach(QGeoCoordinate gc, selGC) { qreal lat = gc.latitude(); qreal lon = gc.longitude(); if (start) { minLat = maxLat = lat; minLon = maxLon = lon; start = false; continue; } if (lat < minLat) minLat = lat; else if (lat > maxLat) maxLat = lat; if (lon < minLon) minLon = lon; else if (lon > maxLon) maxLon = lon; }