diff options
Diffstat (limited to 'qt-ui/globe.cpp')
-rw-r--r-- | qt-ui/globe.cpp | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp deleted file mode 100644 index 135f195a1..000000000 --- a/qt-ui/globe.cpp +++ /dev/null @@ -1,431 +0,0 @@ -#include "globe.h" -#ifndef NO_MARBLE -#include "mainwindow.h" -#include "helpers.h" -#include "divelistview.h" -#include "maintab.h" -#include "display.h" - -#include <QTimer> -#include <QContextMenuEvent> -#include <QMouseEvent> - -#include <marble/AbstractFloatItem.h> -#include <marble/GeoDataPlacemark.h> -#include <marble/GeoDataDocument.h> -#include <marble/MarbleModel.h> -#include <marble/MarbleDirs.h> -#include <marble/MapThemeManager.h> -#include <marble/GeoDataStyle.h> -#include <marble/GeoDataIconStyle.h> -#include <marble/GeoDataTreeModel.h> - -#ifdef MARBLE_SUBSURFACE_BRANCH -#include <marble/MarbleDebug.h> -#endif - -GlobeGPS *GlobeGPS::instance() -{ - static GlobeGPS *self = new GlobeGPS(); - return self; -} - -GlobeGPS::GlobeGPS(QWidget *parent) : MarbleWidget(parent), - loadedDives(0), - messageWidget(new KMessageWidget(this)), - fixZoomTimer(new QTimer(this)), - needResetZoom(false), - editingDiveLocation(false), - doubleClick(false) -{ -#ifdef MARBLE_SUBSURFACE_BRANCH - // we need to make sure this gets called after the command line arguments have - // been processed but before we initialize the rest of Marble - Marble::MarbleDebug::setEnabled(verbose); -#endif - currentZoomLevel = -1; - // check if Google Sat Maps are installed - // if not, check if they are in a known location - MapThemeManager mtm; - QStringList list = mtm.mapThemeIds(); - QString subsurfaceDataPath; - QDir marble; - if (!list.contains("earth/googlesat/googlesat.dgml")) { - subsurfaceDataPath = getSubsurfaceDataPath("marbledata"); - if (subsurfaceDataPath.size()) { - MarbleDirs::setMarbleDataPath(subsurfaceDataPath); - } else { - subsurfaceDataPath = getSubsurfaceDataPath("data"); - if (subsurfaceDataPath.size()) - MarbleDirs::setMarbleDataPath(subsurfaceDataPath); - } - } - messageWidget->setCloseButtonVisible(false); - messageWidget->setHidden(true); - - setMapThemeId("earth/googlesat/googlesat.dgml"); - //setMapThemeId("earth/openstreetmap/openstreetmap.dgml"); - setProjection(Marble::Spherical); - - setAnimationsEnabled(true); - Q_FOREACH (AbstractFloatItem *i, floatItems()) { - i->setVisible(false); - } - - setShowClouds(false); - setShowBorders(false); - setShowPlaces(true); - setShowCrosshairs(false); - setShowGrid(false); - setShowOverviewMap(false); - setShowScaleBar(true); - setShowCompass(false); - connect(this, SIGNAL(mouseClickGeoPosition(qreal, qreal, GeoDataCoordinates::Unit)), - this, SLOT(mouseClicked(qreal, qreal, GeoDataCoordinates::Unit))); - - setMinimumHeight(0); - setMinimumWidth(0); - connect(fixZoomTimer, SIGNAL(timeout()), this, SLOT(fixZoom())); - fixZoomTimer->setSingleShot(true); - installEventFilter(this); -} - -bool GlobeGPS::eventFilter(QObject *obj, QEvent *ev) -{ - // sometimes Marble seems not to notice double clicks and consequently not call - // the right callback - so let's remember here if the last 'click' is a 'double' or not - enum QEvent::Type type = ev->type(); - if (type == QEvent::MouseButtonDblClick) - doubleClick = true; - else if (type == QEvent::MouseButtonPress) - doubleClick = false; - - // This disables Zooming when a double click occours on the scene. - if (type == QEvent::MouseButtonDblClick && !editingDiveLocation) - return true; - // This disables the Marble's Context Menu - // we need to move this to our 'contextMenuEvent' - // if we plan to do a different one in the future. - if (type == QEvent::ContextMenu) { - contextMenuEvent(static_cast<QContextMenuEvent *>(ev)); - return true; - } - if (type == QEvent::MouseButtonPress) { - QMouseEvent *e = static_cast<QMouseEvent *>(ev); - if (e->button() == Qt::RightButton) - return true; - } - return QObject::eventFilter(obj, ev); -} - -void GlobeGPS::contextMenuEvent(QContextMenuEvent *ev) -{ - QMenu m; - QAction *a = m.addAction(tr("Edit selected dive locations"), this, SLOT(prepareForGetDiveCoordinates())); - a->setData(QVariant::fromValue<void *>(&m)); - a->setEnabled(current_dive); - m.exec(ev->globalPos()); -} - -void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) -{ - if (doubleClick) { - // strangely sometimes we don't get the changeDiveGeoPosition callback - // and end up here instead - changeDiveGeoPosition(lon, lat, unit); - return; - } - // don't mess with the selection while the user is editing a dive - if (MainWindow::instance()->information()->isEditing() || messageWidget->isVisible()) - return; - - GeoDataCoordinates here(lon, lat, unit); - long lon_udeg = rint(1000000 * here.longitude(GeoDataCoordinates::Degree)); - long lat_udeg = rint(1000000 * here.latitude(GeoDataCoordinates::Degree)); - - // distance() is in km above the map. - // We're going to use that to decide how - // approximate the dives have to be. - // - // Totally arbitrarily I say that 1km - // distance means that we can resolve - // to about 100m. Which in turn is about - // 1000 udeg. - // - // Trigonometry is hard, but sin x == x - // for small x, so let's just do this as - // a linear thing. - long resolve = rint(distance() * 1000); - - int idx; - struct dive *dive; - bool clear = !(QApplication::keyboardModifiers() & Qt::ControlModifier); - QList<int> selectedDiveIds; - for_each_dive (idx, dive) { - long lat_diff, lon_diff; - struct dive_site *ds = get_dive_site_for_dive(dive); - if (!dive_site_has_gps_location(ds)) - continue; - lat_diff = labs(ds->latitude.udeg - lat_udeg); - lon_diff = labs(ds->longitude.udeg - lon_udeg); - if (lat_diff > 180000000) - lat_diff = 360000000 - lat_diff; - if (lon_diff > 180000000) - lon_diff = 180000000 - lon_diff; - if (lat_diff > resolve || lon_diff > resolve) - continue; - - selectedDiveIds.push_back(idx); - } - if (selectedDiveIds.empty()) - return; - if (clear) - MainWindow::instance()->dive_list()->unselectDives(); - MainWindow::instance()->dive_list()->selectDives(selectedDiveIds); -} - -void GlobeGPS::repopulateLabels() -{ - static GeoDataStyle otherSite, currentSite; - static GeoDataIconStyle darkFlag(QImage(":flagDark")), lightFlag(QImage(":flagLight")); - struct dive_site *ds; - int idx; - QMap<QString, GeoDataPlacemark *> locationMap; - if (loadedDives) { - model()->treeModel()->removeDocument(loadedDives); - delete loadedDives; - } - loadedDives = new GeoDataDocument; - otherSite.setIconStyle(darkFlag); - currentSite.setIconStyle(lightFlag); - - if (displayed_dive_site.uuid && dive_site_has_gps_location(&displayed_dive_site)) { - GeoDataPlacemark *place = new GeoDataPlacemark(displayed_dive_site.name); - place->setStyle(¤tSite); - place->setCoordinate(displayed_dive_site.longitude.udeg / 1000000.0, - displayed_dive_site.latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); - locationMap[QString(displayed_dive_site.name)] = place; - loadedDives->append(place); - } - for_each_dive_site(idx, ds) { - if (ds->uuid == displayed_dive_site.uuid) - continue; - if (dive_site_has_gps_location(ds)) { - GeoDataPlacemark *place = new GeoDataPlacemark(ds->name); - place->setStyle(&otherSite); - place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); - - // don't add dive locations twice, unless they are at least 50m apart - if (locationMap[QString(ds->name)]) { - GeoDataCoordinates existingLocation = locationMap[QString(ds->name)]->coordinate(); - GeoDataLineString segment = GeoDataLineString(); - segment.append(existingLocation); - GeoDataCoordinates newLocation = place->coordinate(); - segment.append(newLocation); - double dist = segment.length(6371); - // the dist is scaled to the radius given - so with 6371km as radius - // 50m turns into 0.05 as threashold - if (dist < 0.05) - continue; - } - locationMap[QString(ds->name)] = place; - loadedDives->append(place); - } - } - model()->treeModel()->addDocument(loadedDives); - - struct dive_site *center = displayed_dive_site.uuid != 0 ? - &displayed_dive_site : current_dive ? - get_dive_site_by_uuid(current_dive->dive_site_uuid) : NULL; - if(dive_site_has_gps_location(&displayed_dive_site) && center) - centerOn(displayed_dive_site.longitude.udeg / 1000000.0, displayed_dive_site.latitude.udeg / 1000000.0, true); -} - -void GlobeGPS::reload() -{ - editingDiveLocation = false; - messageWidget->hide(); - repopulateLabels(); -} - -void GlobeGPS::centerOnDiveSite(struct dive_site *ds) -{ - if (!dive_site_has_gps_location(ds)) { - // this is not intuitive and at times causes trouble - let's comment it out for now - // zoomOutForNoGPS(); - return; - } - qreal longitude = ds->longitude.udeg / 1000000.0; - qreal latitude = ds->latitude.udeg / 1000000.0; - - if(IS_FP_SAME(longitude, centerLongitude()) && IS_FP_SAME(latitude,centerLatitude())) { - return; - } - - // if no zoom is set up, set the zoom as seen from 3km above - // if we come back from a dive without GPS data, reset to the last zoom value - // otherwise check to make sure we aren't still running an animation and then remember - // the current zoom level - if (currentZoomLevel == -1) { - currentZoomLevel = zoomFromDistance(3.0); - centerOn(longitude, latitude); - fixZoom(true); - return; - } - if (!fixZoomTimer->isActive()) { - if (needResetZoom) { - needResetZoom = false; - fixZoom(); - } else if (zoom() >= 1200) { - currentZoomLevel = zoom(); - } - } - // From the marble source code, the maximum time of - // 'spin and fit' is 2000 miliseconds so wait a bit them zoom again. - fixZoomTimer->stop(); - if (zoom() < 1200 && IS_FP_SAME(centerLatitude(), latitude) && IS_FP_SAME(centerLongitude(), longitude)) { - // create a tiny movement - centerOn(longitude + 0.00001, latitude + 0.00001); - fixZoomTimer->start(300); - } else { - fixZoomTimer->start(2100); - } - centerOn(longitude, latitude, true); -} - -void GlobeGPS::fixZoom(bool now) -{ - setZoom(currentZoomLevel, now ? Marble::Instant : Marble::Linear); -} - -void GlobeGPS::zoomOutForNoGPS() -{ - // this is called if the dive has no GPS location. - // zoom out quite a bit to show the globe and remember that the next time - // we show a dive with GPS location we need to zoom in again - if (!needResetZoom) { - needResetZoom = true; - if (!fixZoomTimer->isActive() && zoom() >= 1500) { - currentZoomLevel = zoom(); - } - } - if (fixZoomTimer->isActive()) - fixZoomTimer->stop(); - // 1000 is supposed to make sure you see the whole globe - setZoom(1000, Marble::Linear); -} - -void GlobeGPS::endGetDiveCoordinates() -{ - messageWidget->animatedHide(); - editingDiveLocation = false; -} - -void GlobeGPS::prepareForGetDiveCoordinates() -{ - messageWidget->setMessageType(KMessageWidget::Warning); - messageWidget->setText(QObject::tr("Move the map and double-click to set the dive location")); - messageWidget->setWordWrap(true); - messageWidget->setCloseButtonVisible(false); - messageWidget->animatedShow(); - editingDiveLocation = true; - // this is not intuitive and at times causes trouble - let's comment it out for now - // if (!dive_has_gps_location(current_dive)) - // zoomOutForNoGPS(); -} - -void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) -{ - if (!editingDiveLocation) - return; - - // convert to degrees if in radian. - if (unit == GeoDataCoordinates::Radian) { - lon = lon * 180 / M_PI; - lat = lat * 180 / M_PI; - } - centerOn(lon, lat, true); - - // change the location of the displayed_dive and put the UI in edit mode - displayed_dive_site.latitude.udeg = lrint(lat * 1000000.0); - displayed_dive_site.longitude.udeg = lrint(lon * 1000000.0); - emit coordinatesChanged(); - repopulateLabels(); -} - -void GlobeGPS::mousePressEvent(QMouseEvent *event) -{ - if (event->type() != QEvent::MouseButtonDblClick) - return; - - qreal lat, lon; - bool clickOnGlobe = geoCoordinates(event->pos().x(), event->pos().y(), lon, lat, GeoDataCoordinates::Degree); - - // there could be two scenarios that got us here; let's check if we are editing a dive - if (MainWindow::instance()->information()->isEditing() && clickOnGlobe) { - // - // FIXME - // TODO - // - // this needs to do this on the dive site screen - // MainWindow::instance()->information()->updateCoordinatesText(lat, lon); - repopulateLabels(); - } else if (clickOnGlobe) { - changeDiveGeoPosition(lon, lat, GeoDataCoordinates::Degree); - } -} - -void GlobeGPS::resizeEvent(QResizeEvent *event) -{ - int size = event->size().width(); - MarbleWidget::resizeEvent(event); - if (size > 600) - messageWidget->setGeometry((size - 600) / 2, 5, 600, 0); - else - messageWidget->setGeometry(5, 5, size - 10, 0); - messageWidget->setMaximumHeight(500); -} - -void GlobeGPS::centerOnIndex(const QModelIndex& idx) -{ - struct dive_site *ds = get_dive_site_by_uuid(idx.model()->index(idx.row(), 0).data().toInt()); - if (!ds || !dive_site_has_gps_location(ds)) - centerOnDiveSite(&displayed_dive_site); - else - centerOnDiveSite(ds); -} -#else - -GlobeGPS *GlobeGPS::instance() -{ - static GlobeGPS *self = new GlobeGPS(); - return self; -} - -GlobeGPS::GlobeGPS(QWidget *parent) -{ - setText("MARBLE DISABLED AT BUILD TIME"); -} -void GlobeGPS::repopulateLabels() -{ -} -void GlobeGPS::centerOnCurrentDive() -{ -} -bool GlobeGPS::eventFilter(QObject *obj, QEvent *ev) -{ - return QObject::eventFilter(obj, ev); -} -void GlobeGPS::prepareForGetDiveCoordinates() -{ -} -void GlobeGPS::endGetDiveCoordinates() -{ -} -void GlobeGPS::reload() -{ -} -void GlobeGPS::centerOnIndex(const QModelIndex& idx) -{ -} -#endif |