/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mapbox.h" #include "statswidget.h" #include "boxgraphicsscene.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../../../src/location/maps/qgraphicsgeomap_p.h" #include "../../../../plugins/geoservices/nokia/qgeomappingmanagerengine_nokia.h" #include QNetworkSession * MapBox::m_session = 0; MapBox::MapBox(QWidget *parent) : QWidget(parent), m_qgv(0), m_scene(0), m_mapWidget(0), m_serviceProvider(0), m_mapManager(0) { // We need a session, make sure we get one. Q_ASSERT(m_session); Q_ASSERT(m_session->state() == QNetworkSession::Connected); QString urlEnv = QProcessEnvironment::systemEnvironment().value("http_proxy"); if (!urlEnv.isEmpty()) { QUrl url = QUrl(urlEnv, QUrl::TolerantMode); QNetworkProxy proxy; proxy.setType(QNetworkProxy::HttpProxy); proxy.setHostName(url.host()); proxy.setPort(url.port(8080)); QNetworkProxy::setApplicationProxy(proxy); } else QNetworkProxyFactory::setUseSystemConfiguration(true); m_statistics = new StatsWidget(this); m_scene = new BoxGraphicsScene(m_statistics, this); m_qgv = new QGraphicsView(m_scene, this); m_qgv->setOptimizationFlag(QGraphicsView::IndirectPainting, true); m_qgv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_qgv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QVBoxLayout * layout = new QVBoxLayout(this); layout->setMargin(0); layout->addWidget(m_statistics); layout->addWidget(m_qgv); setLayout(layout); // determine the order of the stat entries m_statistics->stat("FPS", "-"); m_statistics->stat("Render time", "-"); m_statistics->stat("mem", "-"); m_statistics->stat("map objects", "-"); m_statistics->stat("net recv", "-"); m_statistics->stat("net sent", "-"); startTimer(1000); } void MapBox::timerEvent(QTimerEvent * event) { m_statistics->stat("mem", perf_currentMemUsage()); m_statistics->stat("map objects", m_mapWidget->mapObjects().size()); if (m_session) { m_statistics->stat("net recv", m_session->bytesReceived()); m_statistics->stat("net sent", m_session->bytesWritten()); } } MapBox::~MapBox() { } void MapBox::setProvider(const QString & providerId) { if (m_providerId == providerId) return; m_providerId = providerId; createProvider(); } void MapBox::createProvider() { delete m_serviceProvider; m_serviceProvider = new QGeoServiceProvider(m_providerId, m_parameters); if (m_serviceProvider->error() != QGeoServiceProvider::NoError) { QMessageBox::information(this, tr("MapViewer Example"), tr( "Unable to find the %1 geoservices plugin.").arg(m_providerId)); qApp->quit(); } m_mapManager = m_serviceProvider->mappingManager(); createMapWidget(); } void MapBox::createMapWidget() { delete m_mapWidget; m_mapWidget = new QGraphicsGeoMap(m_mapManager); m_mapWidget->setCenter(QGeoCoordinate(52.5, 13.0)); m_mapWidget->setZoomLevel(5); m_scene->addItem(m_mapWidget); } MapBox * MapBox::createOnlineMap(QWidget * parent) { MapBox * mapBox = new MapBox(parent); mapBox->setProvider("nokia"); return mapBox; } MapBox * MapBox::createOfflineMap(QWidget * parent) { MapBox * mapBox = new MapBox(parent); mapBox->setProvider("nokia_mos"); return mapBox; } QNetworkSession * MapBox::session() { if (!m_session) { // Set Internet Access Point QNetworkConfigurationManager manager; const bool canStartIAP = (manager.capabilities() & QNetworkConfigurationManager::CanStartAndStopInterfaces); // Is there default access point, use it QNetworkConfiguration cfg = manager.defaultConfiguration(); if (!cfg.isValid() || (!canStartIAP && cfg.state() != QNetworkConfiguration::Active)) { QMessageBox::information(0, tr("Map Viewer Demo"), tr( "Available Access Points not found.")); qApp->quit(); return 0; } m_session = new QNetworkSession(cfg, 0); // TODO: find a suitable parent /* connect(m_session, SIGNAL(opened()), this, SLOT(networkSessionOpened())); connect(m_session, SIGNAL(error(QNetworkSession::SessionError)), this, SLOT(error(QNetworkSession::SessionError))); */ // call asynchronously to ensure the caller gets a chance to connect before events are fired. QTimer::singleShot(0, m_session, SLOT(open())); } return m_session; } void MapBox::resizeEvent(QResizeEvent * event) { m_qgv->setSceneRect(QRectF(QPointF(0.0, 0.0), m_qgv->size())); if (m_mapWidget) m_mapWidget->resize(m_qgv->size()); QWidget::resizeEvent(event); } static QPen defaultPen() { QPen pen(Qt::white); pen.setWidth(2); pen.setCosmetic(true); return pen; } static QBrush defaultBrush() { return QBrush(QColor(0,0,0,65)); } QGeoMapRectangleObject * MapBox::addRectangle(qreal top, qreal left, qreal bottom, qreal right) { return addRectangle(QGeoCoordinate(top, left), QGeoCoordinate(bottom, right)); } QGeoMapRectangleObject * MapBox::addRectangle(const QGeoCoordinate & topLeft, const QGeoCoordinate & bottomRight) { QGeoMapRectangleObject *rectangle = new QGeoMapRectangleObject(topLeft, bottomRight); rectangle->setPen(defaultPen()); rectangle->setBrush(defaultBrush()); m_mapWidget->addMapObject(rectangle); return rectangle; } QGeoMapPolylineObject * MapBox::addPolyline(const QList & path) { QGeoMapPolylineObject *polyline = new QGeoMapPolylineObject(); polyline->setPen(defaultPen()); polyline->setPath(path); m_mapWidget->addMapObject(polyline); return polyline; } QGeoMapPolygonObject * MapBox::addPolygon(const QList & path) { QGeoMapPolygonObject *polygon = new QGeoMapPolygonObject(); polygon->setPen(defaultPen()); polygon->setBrush(defaultBrush()); polygon->setPath(path); m_mapWidget->addMapObject(polygon); return polygon; } QGeoMapCircleObject * MapBox::addCircle(const QGeoCoordinate & center, qreal radius) { QGeoMapCircleObject *circle = new QGeoMapCircleObject(center, radius); circle->setPen(defaultPen()); circle->setBrush(defaultBrush()); m_mapWidget->addMapObject(circle); return circle; } void MapBox::addRoute(const QGeoCoordinate & start, const QGeoCoordinate & end) { QList waypoints; waypoints << start << end; addRoute(waypoints); } void MapBox::addRoute(const QList & waypoints) { QGeoRoutingManager * routingManager = m_serviceProvider->routingManager(); QGeoRouteRequest req(waypoints); QGeoRouteReply *reply = routingManager->calculateRoute(req); QObject::connect(reply, SIGNAL(finished()), this, SLOT(routeFinished())); } void MapBox::routeFinished() { QGeoRouteReply *reply = static_cast(sender()); if (!reply) return; if (reply->routes().size() < 1) return; QPen pen(QColor(0, 0, 255, 127)); // blue, semi-transparent pen.setWidth(7); //pen.setCosmetic(true); pen.setCapStyle(Qt::RoundCap); QGeoMapRouteObject *route = new QGeoMapRouteObject(reply->routes().at(0)); route->setPen(pen); m_mapWidget->addMapObject(route); } void MapBox::clearCache() { QGeoMappingManagerEngineNokia * engineNokia = 0; foreach (QObject * child, m_mapManager->children()) { engineNokia = dynamic_cast(child); if (engineNokia) break; } Q_ASSERT(engineNokia); QNetworkAccessManager * nam = 0; foreach (QObject * child, engineNokia->children()) { nam = dynamic_cast(child); if (nam) break; } Q_ASSERT(nam); QAbstractNetworkCache * cache = nam->cache(); QNetworkDiskCache * diskCache = dynamic_cast(cache); Q_ASSERT(diskCache); diskCache->clear(); } void MapBox::setParameter(const QString & parameter, const QVariant & value) { m_parameters[parameter] = value; // TODO: defer provider re-creation? createProvider(); } QPixmap MapBox::grab() { Q_ASSERT(m_qgv); return QPixmap::grabWidget(m_qgv); } qreal MapBox::squareError(MapBox * other) { return squareError(other->grab()); } qreal MapBox::squareError(const QPixmap & otherPixmap) { return squareError(otherPixmap.toImage()); } qreal MapBox::squareError(const QImage & otherImage) { QPixmap me = grab(); QImage meImage = me.toImage(); return squareError(meImage, otherImage); } qreal MapBox::squareError(const QImage & image1, const QImage & image2) { qreal delta = 0.0; for (int y = 0; y < image1.height(); ++y) { for (int x = 0; x < image1.width(); ++x) { QRgb val1 = image1.pixel(x,y); QRgb val2 = image2.pixel(x,y); qreal deltaR = qRed(val1) - qRed(val2); qreal deltaG = qGreen(val1) - qGreen(val2); qreal deltaB = qBlue(val1) - qBlue(val2); delta += deltaR*deltaR + deltaG*deltaG + deltaB*deltaB; } } return std::sqrt(delta / (image1.height()*image1.width())); } int MapBox::countErrors(MapBox * other) { return countErrors(other->grab()); } int MapBox::countErrors(const QPixmap & otherPixmap) { return countErrors(otherPixmap.toImage()); } int MapBox::countErrors(const QImage & otherImage) { QPixmap me = grab(); QImage meImage = me.toImage(); return countErrors(meImage, otherImage); } int MapBox::countErrors(const QImage & image1, const QImage & image2) { int errors = 0; for (int y = 0; y < image1.height(); ++y) { for (int x = 0; x < image1.width(); ++x) { QRgb val1 = image1.pixel(x, y); QRgb val2 = image2.pixel(x, y); if ( qRed(val1) != qRed(val2) || qGreen(val1) != qGreen(val2) || qBlue(val1) != qBlue(val2) ) { ++errors; } } } return errors; } /* TODO - make it possible to change the server (already possible through setParameter("mapping.host", "hostname")) addRoute doesn't work and freezes on exit if used statistics panel - mem more plattforms? - network traffic - from other sources than the session, for the desktop - Windows: Network Monitor http://blogs.technet.com/netmon/archive/2008/09/17/network-monitor-3-2-has-arrived.aspx - render mode - sw/hw, but that's pretty static, no? */