diff options
Diffstat (limited to 'examples/location/geojson_viewer/doc/src/geojson_viewer.qdoc')
-rw-r--r-- | examples/location/geojson_viewer/doc/src/geojson_viewer.qdoc | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/examples/location/geojson_viewer/doc/src/geojson_viewer.qdoc b/examples/location/geojson_viewer/doc/src/geojson_viewer.qdoc new file mode 100644 index 00000000..b90c02b8 --- /dev/null +++ b/examples/location/geojson_viewer/doc/src/geojson_viewer.qdoc @@ -0,0 +1,190 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example geojson_viewer + \title GeoJson Viewer (C++/QML) + \ingroup qtlocation-examples + + \brief The GeoJson viewer example demonstrates how to manipulate MapItems, handle user input + and I/O to and from a GeoJson file. + + \image geojson_viewer.png + + The example displays a map with various MapItems. The MapItems are either imported from a + GeoJson file, using the \l {QGeoJson} API of \l {QtLocation} or drawn by the user using + \l {TapHandler}{TapHandlers}. + + Examples for GeoJson files can be found in the directory data within the example directory. + They are read and written using the \l {QGeoJson::importGeoJson}{importGeoJson} and + \l {QGeoJson::exportGeoJson}{exportGeoJson} functions. + + To draw a MapItem, right click on an empty part of the map and select an item type of your + choice in the appearing menu. The next clicks will define the chosen item. The example allows + to draw \l {MapCircle}{MapCircles}, \l {MapRectangle}{MapRectangles}, \l {MapPolygon}{MapPolygons} + and \l {MapPolyline}{MapPolylines}. Items that are fully defined by two points, i.e. circles + and rectangles, are drawn with two clicks of the left mouse button. Items that are defined by + multiple points, i.e. polygons and polylines, are created by an arbitrary amount of left button + clicks and completed with the right mouse button. Items drawn this way are saved as points, + polygons and polylines to fit the GeoJson specification, see \l {https://geojson.org/}. + + + \include examples-run.qdocinc + + + \section1 Creating a MapView + + First we create a base map on which all items can be placed on. We take advantage of a + \l {MapView} element that combines a basic \l Map with input handling (mouse wheel, drag, + etc.). The underlying \l Map can be accessed with \l {MapView::map}{map} property. If you miss + a property in \l {MapView} it can be most likely accessed with \l {MapView::map}{MapView.map}. + + \snippet geojson_viewer/main.qml MapView Creation + + + \section1 Setting up the GeoJson Model / Display MapItems + + In order to display file contents on the map we will use a design pattern known as + \l {model-view-programming}{Model/View Programming}. First we need to set up a suitable view, + in this example a \l {MapItemView} element. Its parent must be set to the underlying map of the + \l {MapView} to correctly display all items placed in it. + + \snippet geojson_viewer/main.qml MapItemView + + Next we need a suitable model, representing a GeoJson file. The GeoJson file is converted into + a tree of \l {QVariantMap}{QVariantMaps} and \l{QVariantList}{QVariantLists} within a C++ class + in this example. + + \snippet geojson_viewer/main.cpp GeoJsoner + + The class contains a member \c{model} which will be set after reading a GeoJson file. + + \snippet geojson_viewer/main.cpp Conversion QVariantList + + The class is made available to the QML Engine to further process the model in QML. + + \snippet geojson_viewer/main.cpp QMLEngine + + The \l {MapItemView::model}{model} property of the \l{MapItemView} element can then be set to + the \l{QVariant} representation of the model: + + \snippet geojson_viewer/main.qml MapItemView Model + + Finally we need a delegate, translating the model data into a representation of items, filling + the \l {MapItemView}. It is set to the \l {MapItemView::delegate}{delegate} property of the + \l{MapItemView}: + + \snippet geojson_viewer/main.qml MapItemView Delegate + + We use a \l {DelegateChooser} element defined the file \c{GeoJsonDelegate.qml} to take into + account the varying representation of different geometry types of GeoJson objects. + + \snippet geojson_viewer/GeoJsonDelegate.qml DelegateChooser + + Various \l {DelegateChoice}{DelegateChoices} are included, each representing a different + geometry type to be found in a GeoJson file. The property \l {DelegateChooser::role}{role} + will be matched with \l {DelegateChoice::roleValue}{DelegateChoice.roleValue} to determine the + correct delegate. + + As an example, a point, described with \c {"type":"Point"} in GeoJson, is represented by a + \l {MapCircle} on the \l {MapItemView}: + + \snippet geojson_viewer/GeoJsonDelegate.qml DelegateChoice Point + + Properties of the \l {MapCircle}, such as \l {MapCircle::color}{color} or + \l{MapCircle::radius}{radius} are attempted to be read from the GeoJson file that is + available in form of the modelData property. However, this is not a strict standard of GeoJson + and fallback values are set for all properties. + + + \section1 Writing MapItems to GeoJson + + To write MapItems to a GeoJson file we first will convert the Mapitems into a representation + of \l {QVariantMap}{QVariantMaps} and \l{QVariantList}{QVariantLists}. This is conducted in C++ + in this example, as part of the \c {GeoJsoner} class used before: + + \snippet geojson_viewer/main.cpp Conversion QVariantList From Items + + \c {extractor} is a helper class that converts Mapitems into \l {QVariant} representations, for + example the \l{MapCircle}: + + \snippet geojson_viewer/main.cpp Extractor Example Circle + + In a second step the \l {QVariant} representation can be dumped into a file using + \l {QJsonDocument}. + + \snippet geojson_viewer/main.cpp Write QVariantList to Json + + The two C++ functions that are required for writing files can be called from QML, thanks to the + definition as \l {Q_INVOKABLE}: + + \snippet geojson_viewer/main.qml Write File + + Note that we could use \c {geoJsoner.model} instead of rebuilding the \l {QVariant} + representation. However, the latter is done for demonstration purposes here. + + \section1 User Interaction with MapItems + + To handle user interactions we will use \l {PointHandler}{PointHandlers}. They are especially + well suited for the task as they conform to the exact shape of the underlying item, in contrast + to \l{MouseArea}{MouseArea}, which always covers a square shape. MapItems that are imported + from a GeoJson file get their own \l {HoverHandler} and \l {TapHandler} directly in the delegate: + + \snippet geojson_viewer/GeoJsonDelegate.qml Handler Point + + The \l {TapHandler} is used to write some information about the item on the console when the + item is tapped. The \l {HoverHandler} is used to highlight items that lie beneath the mouse + pointer. This is implemented by describing the property + \l {MapCircle::border::color}{border.color} depending on the property / state + \l {HoverHandler::hovered}{hovered} of the \l{HoverHandler}. + + + \section1 Adding new Items + + A combination of \l {HoverHandler} and \l {TapHandler} for the \l {MapView} allows us to + react to mouse movements and clicks by the user. + + If the \l{TapHandler} emits a \l{TapHandler::singleTapped}{singleTapped} signal, we will + create or modify a new MapItem on \l{Qt::LeftButton}{LeftButton} and finish the MapItem on + \l{Qt::RightButton}{RightButton}. If there is no item to finish then the + \l{Qt::RightButton}{RightButton} will open a menu. + + \snippet geojson_viewer/main.qml Taphandler Map + + The \l {HoverHandler::pointChanged}{pointChanged} signal is used to temporarily update a + MapItem, giving the user a preview. + + \snippet geojson_viewer/main.qml Hoverhandler Map + + Mapitems are generated from prototypes that are defined in separate qml files. They are created + using the \l{Qt::createComponent}{createComponent} function and added to the map with + \l {Map::addMapItem}{addMapItem}. A reference to the new item is stored for further manipulation + by the user. + + \snippet geojson_viewer/main.qml add item + + + Adding the item to the \l {Map} is sufficient to display the item. However, in order to + further use the item (e.g. saving it to a file), it has has to be registered with the model. + This is done after editing is finished: + + \snippet geojson_viewer/main.qml finish item + + The class GeoJsoner converts the new item into a \l {QVariant} representation and inserts the + respective result into the existing \l {QVariant} representation of all items: + + \snippet geojson_viewer/main.cpp add item + + + \section1 Removing Items + + To remove all items from the map, we simply reset the model to an empty \l {QVariantList}. + This is possible because we registered all new items with the model and items not added to the + mode will not be affected. This is implemented in C++, + + \snippet geojson_viewer/main.cpp clear + + and executed from QML + + \snippet geojson_viewer/main.qml clearAllItems +*/ |