Briefly on how to make your Qt geoservice plugin
The next step after GPS module, became its practical application in my project. Maybe someone this post will be more interesting.
First, some source data:
Required:
the
- Integration with QML
Offline mapping service the
Features:
the
-
the
- libosmscout — library providing the OSM data in the wrapper with the friendly API the
- Qt5Location with dev branch
summary of the previous 160 series
In Qt since time immemorial was a wonderful beam-process QtMobility and he was so wonderful that he lived, he lived, and bent. Yes, of course, he is still here, and even used my N9 and someone's Blackberry, but the fact that Digia will no longer support this API at all.
But in Digia are working not fools, they gradually started to pull the pieces QtMobility in Qt5. One such component is a QtLocation. In Qt 5.3, you can see only a piece QtLocation, QtPositioning which refers to Digia. I must say nice stuff, gave her the NMEA from the local socket, and she'll answer obektik on a silver platter. Everything is great, but why should I position if there is no card? There Digia probably have asked the same question, and in Qt5.4 I hope she unreleased QtLocation with all its buns.
getting started
I won't be in the article to describe how to build Qt from source, since there is a plethora of intricacies associated with the platform on which the build. Go directly to the software part.
To start, create a directory in which there will be a plugin, for example <path to source code QtLocation>/src/plugins/geoservices/osmscout
Then create a project file osmscout.pro (can there be any other name) as follows:
the
TARGET = qtgeoservices_osmscout #the name of your library, in the end will be something like this libqtgeoservices_osmscout.so
QT += location-private placement-private network #specify the pieces of Qt that will be used in the project
#linking with libraries and add the paths to the header files
#happen automatically
PLUGIN_TYPE = geoservices #type of the plugin, then you just need to believe in the word
PLUGIN_CLASS_NAME = QGeoServiceProviderFactoryOsmScout # class name, which will be implemented by the access interfaces of the plugin
load(qt_plugin) #qt_plugin performed.prf for the final settings of the plugin based on the variables above
Great! What we have all done well. You can now open the project in QtCreator and
Add a class that we promised qt_plugin' — QGeoServiceProviderFactoryOsmScout.
the
class QGeoServiceProviderFactoryOsmScout: public QObject, public QGeoServiceProviderFactory
{
Q_OBJECT //Who knows what it is leave I did not call you!
Q_INTERFACES(QGeoServiceProviderFactory) //This macro obviously slushaetsya qmake preprocessor like previous
//and unfold it into something beautiful. What is hard to say - not watching.
Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0"
FILE "osmscout_plugin.json") // This is a more interesting lines, they are slightly below.
public:
QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters,
QGeoServiceProvider::Error *error,
QString *errorString) const; //interfaces for now I'll just mapping, I'm going to implement.
};
In addition to the method createMappingManagerEngine you can also implement one of the following interfaces:
the
virtual QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters,
QGeoServiceProvider::Error *error,
QString *errorString) const; // the Interface provides geocoding
virtual QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters,
QGeoServiceProvider::Error *error,
QString *errorString) const; // Interface provides routing
virtual QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters,
QGeoServiceProvider::Error *error,
About the Q_PLUGIN_METADATA macro, it is treated similarly many qmake macros by the preprocessor. We only important arguments:
IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" is a common identifier of the interface that we are implementing
FILE "osmscout_plugin.json" file with a detailed description of what we certainly have realized.
About the mysterious and mysticism file osmscout_plugin.json
Regarding file format, I think the questions asked, but on the content of the questions large. The answer to these questions can give only the source code, perhaps in the future it will be somewhere documented most Digia.
So, the fields are:
the
"Keys":<array[string]> - honestly hard to say what it is and what it eats. In the code, some specific references are not found, and did not look particularly. Probably why you need something.
"Provider":<string> - provider name for use in QML/meta interface
Version:<int> - the version of the provider, the format of <major>:<minor>:<patch>
"Experimental":<bool> - there is an interesting point. If you put the Experimental flag to true other things being equal Your plugin will not be visible in the application. To make such plugins available, you need to set "allowExperimental" flag in QDeclarativeGeoServiceProvider your card. How to do it later in the QML part
"Features":<array[string]> - in this field you can push nepijem, so the description just below
Features are divided into categories:
-
the
- RoutingFeature — feature routing
theNoRoutingFeatures — Routing is not supported(K. O.: this option can be omitted)
- GeocodingFeature features geocoding
theNoGeocodingFeatures — the Geocoding is not supported
- MappingFeature features of cartography
theNoMappingFeatures — Mapping not supported
- PlacesFeature features Point-of-interest
theNoPlacesFeatures — Point-of-interest is not supported
OnlineRoutingFeature — Support online routing
OfflineRoutingFeature — Supports offline routing
LocalizedRoutingFeature — Support routing with localization
RouteUpdatesFeature — Support dynamic updates
AlternativeRoutesFeature — Support for multiple alternative routes
ExcludeAreasRoutingFeature — Support for excluding factors routing
AnyRoutingFeatures — Support for just what you want for routing
the
OnlineGeocodingFeature — Supports online geocoding
OfflineGeocodingFeature — Support for offline geocoding
ReverseGeocodingFeature — Support for reverse geocoding
LocalizedGeocodingFeature — Support for geocoding localization
AnyGeocodingFeatures — All of the above except NoGeocodingFeatures
the
OnlineMappingFeature — Support for online maps
OfflineMappingFeature — Support for offline maps
LocalizedMappingFeature — Support for maps with localization
AnyMappingFeatures -All of the above except NoMappingFeatures
the
OnlinePlacesFeature — Support online Point-of-interest
OfflinePlacesFeature — Support for offline Point-of-interest
SavePlaceFeature — Support to save custom points on the map
RemovePlaceFeature — Support for removal of Point-of-interes, on the map
SaveCategoryFeature — Creating and maintaining custom categories Point-of-interest
RemoveCategoryFeature — Deleting categories Point-of-interest
PlaceRecommendationsFeature — Support recommended Point-of-interest according to key words
SearchSuggestionsFeature — Support suggestions according to the search query
LocalizedPlacesFeature — localization Support for Point-of-interes
NotificationsFeature — Support of notifications about changes in Point-of-interes
PlaceMatchingFeature — Support comparison of Point-of-interes from two different providers
AnyPlacesFeatures — You need to relax
From myself I will add:
a file with the description of the interfaces Your plugin is a kind of promise to the user what he can do with it.
Conclusion: do not promise more than can your plugin Stabia function something like:
Neither you nor the user to anything.
My interface is quite simple, the bottom line I got this:
the
{
"Keys": ["osmscout"],
"Provider": "osmscout",
"Version": 100,
"Experimental": false,
"Features": [
"OfflineMappingFeature"
]
}
Implementation of map service
As was seen above, the interface of our plug-in undertakes to return the user QGeoMappingManagerEngine. I am now actively picking their vector maps with continuous rendering, but nothing yet sane enough to show not ready. So tell us about the already existing and well working
You will need to inherit from QGeoTiledMappingManagerEngine, which carries a stack of responsibilities on the part of the programmer.
On the basis of RAII in the constructor, do the following:
the
QGeoCameraCapabilities cameraCaps;
cameraCaps.setMinimumZoomLevel(0.0);
cameraCaps.setMaximumZoomLevel(19.0);
setCameraCapabilities(cameraCaps); //Set map supported levels of approximation
//here you can Express support for any vkusnyashek
//the type of the declination of the card relative to the horizon, etc.
setTileSize(QSize(256, 256));//Size of the tile. The selected standard for OSM size
//which according to themselves is dictated by OSM Google.
setCacheHint(QGeoTiledMappingManagerEngine::MemoryCache);//This option exposed going
//since we generate the tiles according to the data from the hard disk
//store them in a disk cache makes no sense.
QList<QGeoMapType> mapTypes;
mapTypes << QGeoMapType(QGeoMapType::StreetMap, tr("Day Street Map"), tr("OpenStreetMap street map"), false, false, OsmScoutDefaultDayMap);
setSupportedMapTypes(mapTypes);//Types of supported card.
//Option is necessary for example in the presence of different styling or satellite maps
QGeoTileFetcherOsmScout *tileFetcher = new QGeoTileFetcherOsmScout(this);//Create loader tiles
setTileFetcher(tileFetcher);
Go deeper
There are two key class which you must implement to get the result:
The heir and the heir QGeoTileFetcher QGeoTiledMapReply.
QGeoTileFetcher requires overriding only one interface:
the
QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec);
This method should return a pointer to an object of a class extended from QGeoTiledMapReply in accordance with QGeoTileSpec. QGeoTileSpec determines the specification of the tile.
Key in this are the following fields:
the
zoom is the zoom level that is being requested.
x — position of the tile in the Mercator projection horizontal
y — position of the tile in the Mercator projection vertically
For someone might be useful ostavshiesya 2 fields mapId, version.
a Small educational program on a grid of tiles
For those who don't know the tiles in OSM and Google have staked out under him room.
Rooms are allocated left-to-right, top-to-bottom on the Mercator projection, broken into 2zoom sectors.
Read more you can read about it here.
For me, the most important from this article was the formula of reverse conversion of rooms and tiles in geographic coordinates, since libosmscout that I used maintained communication only by means of geographic coordinates:
For QGeoTileFetcher nothing more to say. But QGeoTiledMapReply is. The heir in this class must perform 4 functions:
the
-
the
- void setMapImageData(const QByteArray &data) — put data of the tile in the QGeoTiledMapReply the
- void setMapImageFormat(const QString &format) specify the format in which based on data of the tile the
- void setFinished(bool finished) is reported QGeoTileFetcher'that we were finished with this QGeoTiledMapReply the
- void setError(Error error, const QString &errorString) — set error code in case something went wrong
some advice:
Method getTileImage(const QGeoTileSpec &spec) is called in the graphics thread of the application, hence the unpleasant moment — if it takes any significant time, the GUI freezes. Exit getTileImage the sooner the better, rendering/downloading/processing map tiles do in a separate thread.
When ready
Qt very ideological framework and any idea in it leads to the result. In the case of our plugin after successful implementation it suffices to create a new QML project, and with just a few lines to the map:
the
import QtQuick 2.0
import QtLocation 5.3
import QtPositioning 5.2
Rectangle {
id: rect
width: 800
height: 600
Map {
id: map
anchors.fill: parent
plugin: Plugin {
name:"osmscout" //Name of our plugin to write here
allowExperimental: true //Allow experimental plugins
}
}
}
why I wrote it
The finished plugin can be found in my fork of qt-location on gitorious:
qt.gitorious.org/qt/qtlocation-semlanik/source/798639ef13821155730cb83abac7e7821506df31:
It uses libosmscout as offline the framework, my fork from it on sourceforge:
sourceforge.net/u/semlanik/libosmscout/ci/master/tree
And of course all of this works in conjunction with GPS module:
This is all done for my OpenAutomotive of the project.
Thank you all mastered.
Комментарии
Отправить комментарий