+/*
+ * GPSData for Maemo.
+ * Copyright (C) 2011 Roman Moravcik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <QtGui>
+#include <QString>
+#include <QChar>
+#include <qnumeric.h>
+
+#ifdef Q_OS_SYMBIAN
+#include <eikenv.h>
+#include <eikappui.h>
+#include <aknenv.h>
+#include <aknappui.h>
+#endif
+
+#ifdef Q_WS_MAEMO_5
+#include <QtDBus>
+#endif
+
+#include "mainwindow.h"
+#include "gpscompasswindow.h"
+#include "satelliteviewwindow.h"
+
+#ifdef Q_OS_SYMBIAN
+#include "satellitesignalstrengthwindow.h"
+#endif
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
+{
+ m_satellitesInView = 0;
+ m_satellitesInUse = 0;
+#ifdef Q_WS_MAEMO_5
+ m_screenLocked = false;
+#endif
+
+ m_position = QGeoPositionInfoSource::createDefaultSource(0);
+ if (m_position) {
+ connect(m_position, SIGNAL(positionUpdated(const QGeoPositionInfo &)), this,
+ SLOT(onPositionUpdated(const QGeoPositionInfo &)));
+
+ m_position->setUpdateInterval(3);
+ m_position->startUpdates();
+ }
+
+ m_satellite = QGeoSatelliteInfoSource::createDefaultSource(0);
+ if (m_satellite) {
+ connect(m_satellite, SIGNAL(satellitesInViewUpdated(const QList<QGeoSatelliteInfo> &)), this,
+ SLOT(onSatellitesInViewUpdated(const QList<QGeoSatelliteInfo> &)));
+ connect(m_satellite, SIGNAL(satellitesInUseUpdated(const QList<QGeoSatelliteInfo> &)), this,
+ SLOT(onSatellitesInUseUpdated(const QList<QGeoSatelliteInfo> &)));
+
+ m_satellite->startUpdates();
+ }
+
+ createUi();
+ createMenu();
+ updateUi();
+
+#ifdef Q_WS_MAEMO_5
+ registerScreenLockMonitor();
+#endif
+}
+
+MainWindow::~MainWindow()
+{
+ if (m_satellite) {
+ m_satellite->stopUpdates();
+ delete m_satellite;
+ }
+
+ if (m_position) {
+ m_position->stopUpdates();
+ delete m_position;
+ }
+}
+void MainWindow::createUi()
+{
+ QWidget *widget = new QWidget;
+ setCentralWidget(widget);
+
+#ifdef Q_OS_SYMBIAN
+ const CAknAppUiBase::TAppUiOrientation uiOrientation = CAknAppUi::EAppUiOrientationPortrait;
+ CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi());
+ TRAPD(error,
+ if (appUi)
+ appUi->SetOrientationL(uiOrientation);
+ );
+ Q_UNUSED(error)
+#elif defined(Q_WS_MAEMO_5)
+ setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+
+ setWindowTitle(tr("GPSData"));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout();
+ widget->setLayout(mainLayout);
+
+ QFormLayout *layout = new QFormLayout();
+ layout->setMargin(8);
+ layout->setSpacing(8);
+ layout->setLabelAlignment(Qt::AlignLeft);
+ mainLayout->addLayout(layout);
+
+ m_latitude = new QLabel();
+ m_latitude->setDisabled(true);
+ layout->addRow(tr("Latitude:"), m_latitude);
+
+ m_longitude = new QLabel();
+ m_longitude->setDisabled(true);
+ layout->addRow(tr("Longtitude:"), m_longitude);
+
+ m_accuracy = new QLabel();
+ m_accuracy->setDisabled(true);
+ layout->addRow(tr("Accuracy:"), m_accuracy);
+
+ m_altitude = new QLabel();
+ m_altitude->setDisabled(true);
+ layout->addRow(tr("Altitude:"), m_altitude);
+
+ m_altitudeAccuracy = new QLabel();
+ m_altitudeAccuracy->setDisabled(true);
+ layout->addRow(tr("Altitude accura.:"), m_altitudeAccuracy);
+
+ m_direction = new QLabel();
+ m_direction->setDisabled(true);
+ layout->addRow(tr("Direction:"), m_direction);
+
+ m_magneticDeclination = new QLabel();
+ m_magneticDeclination->setDisabled(true);
+ layout->addRow(tr("Magnetic declin.:"), m_magneticDeclination);
+
+ m_groundSpeed = new QLabel();
+ m_groundSpeed->setDisabled(true);
+ layout->addRow(tr("Ground speed:"), m_groundSpeed);
+
+ m_verticalSpeed = new QLabel();
+ m_verticalSpeed->setDisabled(true);
+ layout->addRow(tr("Vertical speed:"), m_verticalSpeed);
+
+ m_mode = new QLabel();
+ m_mode->setDisabled(true);
+ layout->addRow(tr("Mode:"), m_mode);
+
+ m_time = new QLabel();
+ m_time->setDisabled(true);
+ layout->addRow(tr("GPS Timestamp:"), m_time);
+
+ m_satUsedView = new QLabel();
+ m_satUsedView->setDisabled(true);
+ layout->addRow(tr("Used/View sat.:"), m_satUsedView);
+
+#ifdef Q_WS_MAEMO_5
+ m_satelliteSignalStrength = new SatelliteSignalStrength();
+ m_satelliteSignalStrength->showTitle(true);
+ mainLayout->addWidget(m_satelliteSignalStrength);
+#endif
+}
+
+void MainWindow::createMenu()
+{
+
+#if defined(Q_OS_SYMBIAN)
+ QAction *menuSoftkey = new QAction(tr("Menu"), this);
+ menuSoftkey->setSoftKeyRole(QAction::PositiveSoftKey);
+ addAction(menuSoftkey);
+
+ QMenu *menu = new QMenu();
+ menuSoftkey->setMenu(menu);
+#else
+ QMenuBar *menu = new QMenuBar();
+ setMenuBar(menu);
+#endif
+
+#ifdef Q_OS_SYMBIAN
+ QAction *satelliteSignalStrengthAction = new QAction(tr("Signal strength"), this);
+ menu->addAction(satelliteSignalStrengthAction);
+ connect(satelliteSignalStrengthAction, SIGNAL(triggered()), this, SLOT(onSatelliteSignalStrengthMenuClicked()));
+#endif
+
+ QAction *satelliteViewAction = new QAction(tr("Satellite view"), this);
+ menu->addAction(satelliteViewAction);
+ connect(satelliteViewAction, SIGNAL(triggered()), this, SLOT(onSatelliteViewMenuClicked()));
+
+ QAction *gpsCompassAction = new QAction(tr("GPS compass"), this);
+ menu->addAction(gpsCompassAction);
+ connect(gpsCompassAction, SIGNAL(triggered()), this, SLOT(onGpsCompassMenuClicked()));
+}
+
+
+void MainWindow::updateUi()
+{
+ /* Don't update if window is not visible */
+ if (!isVisible())
+ return;
+
+ if (m_positionInfo.isValid()){
+ m_latitude->setText(convertCoordinate(m_positionInfo.coordinate().latitude(), LatitudeCoordinate));
+ m_longitude->setText(convertCoordinate(m_positionInfo.coordinate().longitude(), LongitudeCoordinate));
+
+ if ((!qIsNaN(m_positionInfo.coordinate().altitude())) &&
+ (m_positionInfo.coordinate().type() != QGeoCoordinate::InvalidCoordinate)) {
+ m_altitude->setText(formatLength(m_positionInfo.coordinate().altitude()));
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy))
+ m_altitudeAccuracy->setText(formatLength(m_positionInfo.attribute(QGeoPositionInfo::VerticalAccuracy)));
+ else
+ m_altitudeAccuracy->clear();
+ } else {
+ m_altitude->clear();
+ m_altitudeAccuracy->clear();
+ }
+
+ if (m_positionInfo.coordinate().type() == QGeoCoordinate::Coordinate2D)
+ m_mode->setText("2D");
+ else if (m_positionInfo.coordinate().type() == QGeoCoordinate::Coordinate3D)
+ m_mode->setText("3D");
+ else
+ m_mode->clear();
+
+ m_time->setText(m_positionInfo.timestamp().toString("dd.MM.yyyy hh:mm:ss"));
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
+ m_accuracy->setText(formatLength(m_positionInfo.attribute(QGeoPositionInfo::HorizontalAccuracy)));
+ else
+ m_accuracy->clear();
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::GroundSpeed))
+ m_groundSpeed->setText(convertSpeed(m_positionInfo.attribute(QGeoPositionInfo::GroundSpeed)));
+ else
+ m_groundSpeed->clear();
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::VerticalSpeed))
+ m_verticalSpeed->setText(convertSpeed(m_positionInfo.attribute(QGeoPositionInfo::VerticalSpeed)));
+ else
+ m_verticalSpeed->clear();
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::Direction))
+ m_direction->setText(formatDirection(m_positionInfo.attribute(QGeoPositionInfo::Direction)));
+ else
+ m_direction->clear();
+
+ if (m_positionInfo.hasAttribute(QGeoPositionInfo::MagneticVariation))
+ m_magneticDeclination->setText(formatDirection(m_positionInfo.attribute(QGeoPositionInfo::MagneticVariation)));
+ else
+ m_magneticDeclination->clear();
+
+ m_satUsedView->setText(QString::number(m_satellitesInUse) + " / " + QString::number(m_satellitesInView));
+ } else {
+ m_latitude->setText(tr("Waiting for GPS data"));
+ m_longitude->clear();
+ m_accuracy->clear();
+ m_altitude->clear();
+ m_altitudeAccuracy->clear();
+ m_direction->clear();
+ m_groundSpeed->clear();
+ m_verticalSpeed->clear();
+ m_mode->clear();
+ m_time->clear();
+ m_satUsedView->clear();
+ }
+}
+
+QString MainWindow::convertCoordinate(double coordinate, CoordinateType type) const
+{
+ QString s;
+ QChar degree(0x00B0);
+
+ double coordinateAbs = qAbs(coordinate);
+ double coordinateMin = (coordinateAbs - int(coordinateAbs)) * 60;
+ double coordinateSec = (coordinateMin - int(coordinateMin)) * 60;
+
+ s = QString("%1%2 %3' %4\"")
+ .arg(QString::number(int(coordinateAbs)))
+ .arg(degree)
+ .arg(QString::number(int(coordinateMin)))
+ .arg(QString::number(coordinateSec, 'f', 3));
+
+ if (type == LatitudeCoordinate) {
+ if (coordinate > 0)
+ s.append(" N");
+ else
+ s.append(" S");
+ } else {
+ if (coordinate > 0)
+ s.append(" E");
+ else
+ s.append(" W");
+ }
+
+ return s;
+}
+
+QString MainWindow::convertSpeed(double speed) const
+{
+ QString s;
+
+ s.sprintf("%.2f km/h", speed * 3.6);
+
+ return s;
+}
+
+QString MainWindow::formatLength(double length) const
+{
+ QString s;
+
+ if (length > 10000)
+ s.sprintf("%.2f km", length / 10000);
+ else
+ s.sprintf("%.2f m", length);
+
+ return s;
+}
+
+QString MainWindow::formatDirection(double length) const
+{
+ QString s;
+ QChar degree(0x00B0);
+
+ s = QString("%1%2").arg(QString::number(length, 'f', 2)).arg(degree);
+
+ return s;
+}
+
+void MainWindow::onPositionUpdated(const QGeoPositionInfo &position)
+{
+#ifdef Q_WS_MAEMO_5
+ if (m_screenLocked)
+ return;
+#endif
+
+ if (position.isValid()) {
+ m_positionInfo = position;
+ updateUi();
+ }
+}
+
+void MainWindow::onSatellitesInViewUpdated(const QList<QGeoSatelliteInfo> &satellites)
+{
+#ifdef Q_WS_MAEMO_5
+ if (m_screenLocked)
+ return;
+
+ m_satelliteSignalStrength->updateWidget(satellites, false);
+#endif
+ m_satellitesInView = satellites.count();
+ updateUi();
+}
+
+void MainWindow::onSatellitesInUseUpdated(const QList<QGeoSatelliteInfo> &satellites)
+{
+#ifdef Q_WS_MAEMO_5
+ if (m_screenLocked)
+ return;
+
+ m_satelliteSignalStrength->updateWidget(satellites, true);
+#endif
+ m_satellitesInUse = satellites.count();
+ updateUi();
+}
+
+#ifdef Q_OS_SYMBIAN
+void MainWindow::satelliteSignalStrengthMenuClicked()
+{
+ SatelliteSignalStrengthWindow *satelliteSignalStrengthWindow = new SatelliteSignalStrengthWindow(this);
+ satelliteSignalStrengthWindow->setSatelliteInfoSource(m_satellite);
+ satelliteSignalStrengthWindow->showMaximized();
+}
+#endif
+
+void MainWindow::onSatelliteViewMenuClicked()
+{
+ SatelliteViewWindow *satelliteViewWindow = new SatelliteViewWindow(this);
+ satelliteViewWindow->setSatelliteInfoSource(m_satellite);
+#if defined(Q_OS_SYMBIAN)
+ satelliteViewWindow->showMaximized();
+#elif defined(Q_WS_MAEMO_5)
+ satelliteViewWindow->show();
+#endif
+}
+
+void MainWindow::onGpsCompassMenuClicked()
+{
+ GpsCompassWindow *gpsCompassWindow = new GpsCompassWindow(this);
+ gpsCompassWindow->setPositionInfoSource(m_position);
+#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5)
+ gpsCompassWindow->showMaximized();
+#else
+ gpsCompassWindow->show();
+#endif
+}
+
+#ifdef Q_WS_MAEMO_5
+void MainWindow::registerScreenLockMonitor()
+{
+ QDBusConnection::systemBus().connect("",
+ "/com/nokia/mce/signal",
+ "com.nokia.mce.signal",
+ "tklock_mode_ind",
+ this,
+ SLOT(onScreenLocked(QString)));
+}
+
+void MainWindow::onScreenLocked(QString state)
+{
+ bool locked;
+
+ if(state == "unlocked")
+ locked = false;
+ else
+ locked = true;
+
+ if (m_screenLocked != locked) {
+ m_screenLocked = locked;
+ emit screenLocked(m_screenLocked);
+ }
+}
+#endif