From 659c53b0d8faf26e6f06334833b2e105a4c4193d Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Fri, 17 Aug 2012 04:57:27 +0200 Subject: trying to make the map watchlet more useful --- qmapwatchlet/mapview.cc | 175 ++++++++++++++++++++++++++++++++++++ qmapwatchlet/mapview.h | 57 ++++++++++++ qmapwatchlet/metawatch-digital.qml | 21 ++--- qmapwatchlet/qmapwatchlet.cpp | 5 +- qmapwatchlet/qmapwatchlet.h | 2 + qmapwatchlet/qmapwatchlet.pro | 10 +-- qmapwatchlet/qmapwatchletplugin.cpp | 24 ++++- qmapwatchlet/qmapwatchletplugin.h | 6 ++ 8 files changed, 274 insertions(+), 26 deletions(-) create mode 100644 qmapwatchlet/mapview.cc create mode 100644 qmapwatchlet/mapview.h diff --git a/qmapwatchlet/mapview.cc b/qmapwatchlet/mapview.cc new file mode 100644 index 0000000..30e7775 --- /dev/null +++ b/qmapwatchlet/mapview.cc @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include "qmapwatchletplugin.h" +#include "mapview.h" + +QTM_USE_NAMESPACE +using namespace sowatch; + +MapView::MapView(QDeclarativeItem *parent) : + QDeclarativeItem(parent), + _enabled(false), + _mapData(0), + _pos(QGeoPositionInfoSource::createDefaultSource(this)) +{ + QGeoServiceProvider *provider = QMapWatchletPlugin::geoServiceProvider(); + if (!provider) { + qWarning() << "No geo service provider for map watchlet!"; + } + + QGeoMappingManager *manager = provider->mappingManager(); + _mapData = manager->createMapData(); + + if (_mapData) { + _mapData->init(); + _mapData->setMapType(QGraphicsGeoMap::StreetMap); + + _mapData->setZoomLevel(10); + + connect(_mapData, SIGNAL(zoomLevelChanged(qreal)), SIGNAL(zoomLevelChanged())); + connect(_mapData, SIGNAL(updateMapDisplay(QRectF)), SLOT(handleMapChanged(QRectF))); + } else { + qWarning() << "No mapdata!"; + } + + if (_pos) { + connect(_pos, SIGNAL(positionUpdated(QGeoPositionInfo)), + SLOT(handlePositionUpdate(QGeoPositionInfo))); + _pos->lastKnownPosition(); + } else { + qWarning() << "No position source for moving map!"; + } + + setFlag(QGraphicsItem::ItemHasNoContents, false); +} + +MapView::~MapView() +{ + delete _mapData; +} + +bool MapView::updateEnabled() const +{ + return _enabled; +} + +void MapView::setUpdateEnabled(bool enabled) +{ + if (_pos && _enabled != enabled) { + if (enabled) { + qDebug() << "Start position updates"; + _pos->startUpdates(); + } else { + qDebug() << "Stop position updates"; + _pos->stopUpdates(); + } + _enabled = enabled; + + emit updateEnabledChanged(); + } + +} + +int MapView::updateInterval() const +{ + if (_pos) { + return _pos->updateInterval(); + } else { + return 0; + } +} + +void MapView::setUpdateInterval(int msec) +{ + if (_pos) { + _pos->setUpdateInterval(msec); + emit updateIntervalChanged(); + } +} + +qreal MapView::zoomLevel() const +{ + if (_mapData) { + return _mapData->zoomLevel(); + } else { + return -1.0; + } +} + +void MapView::setZoomLevel(qreal level) +{ + if (_mapData) { + _mapData->setZoomLevel(level); + qDebug() << "new zoom level" << level; + } +} + +void MapView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + if (_mapData) { + // Render to an image first + const QSize size(_mapData->windowSize().toSize()); + QImage image(size, QImage::Format_RGB32); + QImage pixmap(size, QImage::Format_MonoLSB); + + const int w = image.width(), h = image.height(); + const int npixels = w * h; + QScopedArrayPointer greys(new qreal[npixels]); + + { + QPainter p(&image); + _mapData->paint(&p, option); + } + + // Convert to a bitmap using some ad-hoc ugly algorithm... + qreal sum = 0; + for (int y = 0; y < h; y++) { + QRgb *l = reinterpret_cast(image.scanLine(y)); + for (int x = 0; x < w; x++) { + const int r = qRed(l[x]), g = qGreen(l[x]), b = qBlue(l[x]); + const qreal grey = r * 0.299f + g * 0.587f + b * 0.114f; + + greys[y * w + x] = grey; + + sum += grey; + } + } + + const qreal avg = sum / npixels; + const qreal thr = avg * 0.9; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + // TODO: Optimize + pixmap.setPixel(x, y, greys[y * w + x] >= thr ? Qt::color1 : Qt::color0); + } + } + + // And render into the watch + painter->drawImage(0, 0, pixmap); + } +} + +void MapView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_UNUSED(oldGeometry); + if (_mapData) { + _mapData->setWindowSize(newGeometry.size()); + } +} + +void MapView::handlePositionUpdate(const QGeoPositionInfo& info) +{ + if (_mapData) { + qDebug() << "Got pos for map"; + _mapData->setCenter(info.coordinate()); + } +} + +void MapView::handleMapChanged(const QRectF &rect) +{ + update(); // Always do full updates +} diff --git a/qmapwatchlet/mapview.h b/qmapwatchlet/mapview.h new file mode 100644 index 0000000..f3e457f --- /dev/null +++ b/qmapwatchlet/mapview.h @@ -0,0 +1,57 @@ +#ifndef MAPVIEW_H +#define MAPVIEW_H + +#include +#include +#include + +namespace sowatch +{ + +using QTM_PREPEND_NAMESPACE(QGeoPositionInfo); +using QTM_PREPEND_NAMESPACE(QGeoMapData); +using QTM_PREPEND_NAMESPACE(QGeoPositionInfoSource); + +class MapView : public QDeclarativeItem +{ + Q_OBJECT + Q_PROPERTY(bool updateEnabled READ updateEnabled WRITE setUpdateEnabled NOTIFY updateEnabledChanged) + Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval NOTIFY updateIntervalChanged) + Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) + +public: + explicit MapView(QDeclarativeItem *parent = 0); + ~MapView(); + + bool updateEnabled() const; + void setUpdateEnabled(bool enabled); + + int updateInterval() const; + void setUpdateInterval(int msec); + + qreal zoomLevel() const; + void setZoomLevel(qreal level); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +signals: + void updateEnabledChanged(); + void updateIntervalChanged(); + void zoomLevelChanged(); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + +private slots: + void handlePositionUpdate(const QGeoPositionInfo& info); + void handleMapChanged(const QRectF& rect); + +private: + bool _enabled; + QGeoMapData *_mapData; + QGeoPositionInfoSource *_pos; +}; + +} + +#endif // MAPVIEW_H diff --git a/qmapwatchlet/metawatch-digital.qml b/qmapwatchlet/metawatch-digital.qml index 16206db..9c054a4 100644 --- a/qmapwatchlet/metawatch-digital.qml +++ b/qmapwatchlet/metawatch-digital.qml @@ -1,23 +1,14 @@ import QtQuick 1.0 import QtMobility.location 1.2 +import com.javispedro.sowatch.metawatch 1.0 +import com.javispedro.sowatch.qmap 1.0 -Rectangle { - width: 96 - height: 96 - - color: "white" - - PositionSource { - id: pos - updateInterval: 5000 - active: watch.active - } - - Map { +MWPage { + MapView { id: map anchors.fill: parent; - plugin : Plugin { name : "nokia" } - center: pos.position.coordinate + updateEnabled: watch.active + updateInterval: 5000; } Connections { diff --git a/qmapwatchlet/qmapwatchlet.cpp b/qmapwatchlet/qmapwatchlet.cpp index 6f39641..82132db 100644 --- a/qmapwatchlet/qmapwatchlet.cpp +++ b/qmapwatchlet/qmapwatchlet.cpp @@ -2,9 +2,12 @@ using namespace sowatch; +const QLatin1String QMapWatchlet::myId("com.javispedro.sowatch.qmap"); + QMapWatchlet::QMapWatchlet(WatchServer* server) : - DeclarativeWatchlet(server, "com.javispedro.sowatch.qmap") + DeclarativeWatchlet(server, myId) { + setFullUpdateMode(true); setSource(QUrl(SOWATCH_QML_DIR "/qmapwatchlet/" + server->watch()->model() + ".qml")); } diff --git a/qmapwatchlet/qmapwatchlet.h b/qmapwatchlet/qmapwatchlet.h index ae8e7ea..8683aae 100644 --- a/qmapwatchlet/qmapwatchlet.h +++ b/qmapwatchlet/qmapwatchlet.h @@ -11,6 +11,8 @@ class QMapWatchlet : public DeclarativeWatchlet Q_OBJECT public: explicit QMapWatchlet(WatchServer* server); + + static const QLatin1String myId; }; } diff --git a/qmapwatchlet/qmapwatchlet.pro b/qmapwatchlet/qmapwatchlet.pro index 734e536..72f588a 100644 --- a/qmapwatchlet/qmapwatchlet.pro +++ b/qmapwatchlet/qmapwatchlet.pro @@ -5,17 +5,13 @@ CONFIG += plugin CONFIG += mobility MOBILITY += location -SOURCES += qmapwatchletplugin.cpp qmapwatchlet.cpp +SOURCES += qmapwatchletplugin.cpp qmapwatchlet.cpp mapview.cc -HEADERS += qmapwatchletplugin.h qmapwatchlet.h +HEADERS += qmapwatchletplugin.h qmapwatchlet.h mapview.h qml_files.files = metawatch-digital.qml icon.png -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../libsowatch/release/ -lsowatch -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../libsowatch/debug/ -lsowatch -else:symbian: LIBS += -lsowatch -else:unix: LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch - +LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch INCLUDEPATH += $$PWD/../libsowatch DEPENDPATH += $$PWD/../libsowatch diff --git a/qmapwatchlet/qmapwatchletplugin.cpp b/qmapwatchlet/qmapwatchletplugin.cpp index e8e1c43..517d167 100644 --- a/qmapwatchlet/qmapwatchletplugin.cpp +++ b/qmapwatchlet/qmapwatchletplugin.cpp @@ -1,28 +1,41 @@ #include "qmapwatchlet.h" +#include "mapview.h" #include "qmapwatchletplugin.h" using namespace sowatch; +QTM_USE_NAMESPACE + +QGeoServiceProvider* QMapWatchletPlugin::_provider; QMapWatchletPlugin::QMapWatchletPlugin(QObject *parent) : QObject(parent) { + QStringList avail = QGeoServiceProvider::availableServiceProviders(); + if (!avail.isEmpty()) { + _provider = new QGeoServiceProvider(avail.first()); + } else { + _provider = 0; + } + qmlRegisterType("com.javispedro.sowatch.qmap", 1, 0, "MapView"); } QMapWatchletPlugin::~QMapWatchletPlugin() { + delete _provider; + _provider = 0; } QStringList QMapWatchletPlugin::watchlets() { QStringList l; - l << "com.javispedro.sowatch.qmap"; + l << QMapWatchlet::myId; return l; } WatchletPluginInterface::WatchletInfo QMapWatchletPlugin::describeWatchlet(const QString &id) { WatchletInfo info; - if (id != "com.javispedro.sowatch.qmap") return info; + if (id != QMapWatchlet::myId) return info; info.name = "Moving map"; info.icon = QUrl::fromLocalFile(SOWATCH_QML_DIR "/qmapwatchlet/icon.png"); return info; @@ -31,8 +44,13 @@ WatchletPluginInterface::WatchletInfo QMapWatchletPlugin::describeWatchlet(const Watchlet* QMapWatchletPlugin::getWatchlet(const QString &id, ConfigKey *config, WatchServer *server) { Q_UNUSED(config); - if (id != "com.javispedro.sowatch.qmap") return 0; + if (id != QMapWatchlet::myId) return 0; return new QMapWatchlet(server); } +QGeoServiceProvider *QMapWatchletPlugin::geoServiceProvider() +{ + return _provider; +} + Q_EXPORT_PLUGIN2(qmapwatchlet, QMapWatchletPlugin) diff --git a/qmapwatchlet/qmapwatchletplugin.h b/qmapwatchlet/qmapwatchletplugin.h index 04ff348..3d10213 100644 --- a/qmapwatchlet/qmapwatchletplugin.h +++ b/qmapwatchlet/qmapwatchletplugin.h @@ -1,6 +1,7 @@ #ifndef QMAPWATCHLETPLUGIN_H #define QMAPWATCHLETPLUGIN_H +#include #include namespace sowatch @@ -18,6 +19,11 @@ public: QStringList watchlets(); WatchletInfo describeWatchlet(const QString &id); Watchlet* getWatchlet(const QString &id, ConfigKey *config, WatchServer *server); + + static QtMobility::QGeoServiceProvider * geoServiceProvider(); + +private: + static QtMobility::QGeoServiceProvider *_provider; }; } -- cgit v1.2.3