|
BLOG
|
ArcGIS Runtime SDK for Qt 100 brought many new features to the SDK, such as Raster support, 3D, Vector Tiles, and much more. Beyond many of these big ticket items, there were also lots of architectural and design improvements to the API that make it much easier and more convenient to develop apps with the SDK. One of my favorite new features of the ArcGIS Runtime SDK for Qt (version 100) is the extensive use of list models throughout the API. List models are data structures similar to to lists or vectors that can be used directly in any of the various views that Qt supports (i.e. ListView, GridView, etc). What this means to you as a developer is that you can very easily take the data returned to you from the Runtime API (like features, graphics, maps, layers, attributes, symbols, attachments, and so on), and display them in a view with no data manipulation or massaging. For example, if I wanted to build a table of contents (TOC) for the operational layers in a map, I could access the Map::operationalLayers property, and this would return to me a list model of the layers in the map. I could then take that list model and pass it directly into a ListView component, and display the data in the ListView. This has many benefits including: It is good practice to separate your UI from your business logic The models and views are dynamic, so if a list model gets updated (e.g. a new layer gets added to the map), the View will update automatically without you writing any code to handle this. For QML, it greatly reduces the amount of imperitive JavaScript code, allowing you to write almost exclusively declarative QML code. Writing as declarative of code as possible is something you should always strive for with QML. Model/view, MVC, MVVM, and other similar concepts have endless resources explaining the benefits of the pattern and how to best architect your application using these patterns. Because of this, this article will not discuss that type of information, but will instead focus on the fundamentals of working with list models coming from ArcGIS Runtime, and how you can integrate them with Qt's various view types. There are 3 main concepts that you will need to understand in order to display your data from a list model in a view: Models, Views, and Delegates. Models Models are lists of data and are found throughout the ArcGIS Runtime. Some examples include a LayerListModel, LegendInfoListModel, AttachmentListModel, and AttributeListModel. Models have a couple of important things to know about as an application developer. The first thing you need to know is what the model contains. In the example of a LayerListModel, you can read in the documentation that it is a list of Layers available in the map. The second important thing to note are the roles available on the model. For example, the LayerListModel has a name and layerVisible role (among many others). These roles are basically the properties that you can access for each item in the list model. With this information, you should begin to see how one could start building a table of contents. Views Views are the UI elements that actually display the data. ListViews and GridViews are some of the most common types. Your phone's music app will likely make heavy use of these types of views, as they might display a list of songs by a particular artist, or they might show a grid of a particular artist's album covers. One important thing to understand is that the View determines what will be shown, but it will not determine how something is shown. For example, in the example of the TOC control, we might know that we want to have a list of layers shown in a view, but the view does not dictate how each element in that list of layers looks (i.e. the text to display, the color of text, the type face, etc). Rather, the delegate controls this information. Delegates Delegates describe what each element in the list will look like. Going back to the TOC example, we know that we want each item show a Checkbox/Switch, so that the user can toggle visibility, and then have the layer name to the right of that. This is where the list model's roles come into play. The delegate can access any of the roles that are exposed and documented in the API reference. The view will use the defined delegate as a template for how to display the data coming out of the model. A simple example To see this all in practice, I suggest you look at the various samples on GitHub. A good, simple example of this is the "Change Sublayer Visibility" sample. This sample has a basemap and a map image layer that contains 3 sublayers: Cities, Continent, and World. We can use the ArcGISSublayerListModel to build a simple TOC where you can see the sublayer name, and toggle the visibility. This section of code contains all of the code related to the TOC control that you see in the upper left of this screenshot. Going back to the previous discussion, there are 3 important things we need: a model, a view, and a delegate. In this case, a ListView is declared, and some anchoring and sizing properties are set. All this is doing is saying that we are going to display a list of something. ListView {
id: layerVisibilityListView
anchors.margins: 10 * scaleFactor
width: parent.width
height: parent.height
clip: true Next you see a model property. This is setting the View's model property to the map service's sublayer list model. model: mapImageLayer.mapImageSublayers Finally, we need a delegate to define how each item in the list will appear. In this case, we want text displaying the layer's name, and a Switch component for toggling visibility. These name and visibility properties are available as the roles "name" and "sublayerVisible" (this can be found the in the documentation for ArcGISSublayerListModel). delegate: Item {
id: layerVisibilityDelegate
width: parent.width
height: 35 * scaleFactor
Row {
spacing: 5
anchors.verticalCenter: parent.verticalCenter
Text {
width: 75 * scaleFactor
text: name // "name" is a role in the list model
wrapMode: Text.WordWrap
font.pixelSize: 14 * scaleFactor
}
Switch {
checked: sublayerVisible // "sublayerVisible" is a role in the list model
onCheckedChanged: {
sublayerVisible = checked;
}
}
}
} All together, this results in the following code for building a basic TOC: // Create a list view to display the items
ListView {
id: layerVisibilityListView
anchors.margins: 10 * scaleFactor
width: parent.width
height: parent.height
clip: true
// Assign the model to the list model of sublayers
model: mapImageLayer.mapImageSublayers
// Assign the delegate to the delegate created above
delegate: Item {
id: layerVisibilityDelegate
width: parent.width
height: 35 * scaleFactor
Row {
spacing: 5
anchors.verticalCenter: parent.verticalCenter
Text {
width: 75 * scaleFactor
text: name
wrapMode: Text.WordWrap
font.pixelSize: 14 * scaleFactor
}
Switch {
checked: sublayerVisible
onCheckedChanged: {
sublayerVisible = checked;
}
}
}
}
} The above example focuses on Qt Quick, but you can utilize these model types with Qt Widgets as well. Many of the same concepts apply, but the workflow differs slightly when working in a QWidgets based UI. To use these with widgets, you can bind the model types to a QAbstractItemView (for example a QTableView) by calling setModel. In order to customise the data you wish to display in the view, a good approach is to create your own QIdentityProxyModel to expose those parts of the underlying model data you wish to use. For example, when using a BasemapListModel you could create your own "BasemapsProxyModel” which takes a BasemapListModel as the sourceModel and returns two columns of data from the full list in the BasemapRoles enum (the basemap title and the snippet which describes it). Your proxy model should then override QIdentityProxyModel::columnCount to return a count of 2. For QIdentityProxyModel::data you should return data from the underlying model based on the column of the supplied QModelIndex. Your code could look something like this: QModelIndex srcIdx = sourceModel()->index(index.row(), 0);
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case 0:
return sourceModel()->data(srcIdx, Esri::ArcGISRuntime::BasemapListModel::BasemapItemTitleRole);
break;
case 1:
return sourceModel()->data(srcIdx, Esri::ArcGISRuntime::BasemapListModel::BasemapItemSnippetRole);
break;
default:
break;
}
} This is only a small introduction to a very large topic. Once these concepts become clear to you, I encourage you to start creating more views for the various models that are exposed in the Runtime API. Here are some additional helpful resources that should help explain model/view programming with Qt. Additional Resources: QML: - QML Book - http://qmlbook.github.io/ch06/ - Models and Views in Qt Quick - http://doc.qt.io/qt-5/qtquick-modelviewsdata-modelview.html - Using C++ Models with Qt Quick Views - http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html Qt Widgets Resources: - Model/View Programming - http://doc.qt.io/qt-5/model-view-programming.html
... View more
08-21-2017
10:34 AM
|
4
|
2
|
2720
|
|
POST
|
This is technically possible by using the various GeometryBuilder classes. You can edit the vertices of the geometry to be where the Mouse cursor is, and update a Graphic's geometry to make the graphic follow it. We plan on eventually implementing a simplified API for this, as well as a toolkit component that will provide UI elements for sketching and editing.
... View more
08-21-2017
07:46 AM
|
2
|
0
|
1077
|
|
POST
|
What version of the SDK are you using? We have a suspicion that this issue is fixed with 100.2, but are not certain.
... View more
08-21-2017
07:43 AM
|
0
|
8
|
2645
|
|
POST
|
Can you please provide some more details, like the version of the SDK you are using, the code that is throwing that exception, details about the data, etc?
... View more
08-21-2017
07:41 AM
|
0
|
0
|
1007
|
|
POST
|
You can modify the brightness, contrast, and gamma on the client side, as ArcGISTiledLayer inherits from ImageAdjustmentLayer - ImageAdjustmentLayer QML Type | ArcGIS for Developers You would need to loop through the layers in your Basemap, and apply the values that you want to each of the layers in the Basemap. Maybe you can combine these properties to get an output that is to your liking.
... View more
08-21-2017
07:28 AM
|
2
|
0
|
1166
|
|
POST
|
Unfortunately not that I am aware of. If you were using your own services, I believe you could use the admin directory to up the max count - ArcGIS REST API - Services and Data Types However, our services have that max restriction in place
... View more
08-11-2017
07:32 AM
|
0
|
0
|
685
|
|
POST
|
A "developer account" should work (I tested with one), because it is an organizational subscription that has access to subscriber content and has credits. A "public account" is different, however, and will not have access to this content and does not have credits. As a test, maybe try creating an account here and see if that works? ArcGIS for Developers
... View more
08-09-2017
07:54 AM
|
0
|
0
|
3689
|
|
POST
|
That might be related to the issue - I tried with a few different accounts and can add those basemaps to the map viewer and save them. What account are you using?
... View more
08-09-2017
07:34 AM
|
0
|
2
|
3689
|
|
POST
|
Interesting, I too can reproduce this with the below code. If you have a technical support, I suggest you open a case so they can file an official bug report. Thank you. // Create the Widget view
m_mapView = new MapGraphicsView(this);
m_mapView->setWrapAroundMode(WrapAroundMode::Disabled);
m_map = new Map(Basemap::streets(this), this);
//m_map = new Map(Basemap::imagery(this), this);
connect(m_mapView, &MapGraphicsView::mouseClicked, this, [=](QMouseEvent e)
{
QDateTime date;
m_startTime = date.currentMSecsSinceEpoch();
m_mapView->identifyLayers(e.x(), e.y(), 10, false, 100);
});
connect(m_mapView, &MapGraphicsView::identifyLayersCompleted, this, [=]()
{
QDateTime date;
qDebug() << "identify done. time elapsed" << date.currentMSecsSinceEpoch() - m_startTime;
});
// Set map to map view
m_mapView->setMap(m_map);
// set the mapView as the central widget
setCentralWidget(m_mapView);
... View more
08-08-2017
03:40 PM
|
0
|
0
|
1978
|
|
POST
|
Kai- A couple of things might be going on. 1) Can you try adding one of the basemaps from this list? http://www.arcgis.com/home/group.html?id=3a890be7a4b046c7840dc4a0446c5b31&start=1&view=list&sortOrder=asc&sortField=titl… These basemaps support the "export tiles" REST endpoint, which is required to take the basemap offline. Many basemaps auto-redirect to the appropriate export tiles version of the service (for example, if you add the regular World Imagery and try to take that offline, it will automatically switch to use the World Imagery (for export) service), but it seems we missed Nat Geo in that list. 2) I may have led you astray with the suggestion to use the constructor with the credential in it. Instead, you should use the AuthenticationManager. The AuthenticationManager is basically a singleton class that emits a signal whenever a new authentication challenge comes through. If you create a Map that is private, but don't provide a credential, the AuthenticationManager will emit a signal indicating that a credential is required, and you can then create the credential and set it there. What this will do is add the credential to the credential cache, so that the API can automatically start using that credential for further authentication challenges. Here is the doc for this class AuthenticationManager Class | ArcGIS for Developers , and here is a sample of using the AuthenticationView QML toolkit control to handle most of it for you arcgis-runtime-samples-qt/ArcGISRuntimeSDKQt_CppSamples/CloudAndPortal/TokenAuthentication at master · Esri/arcgis-runti…
... View more
08-07-2017
08:52 AM
|
0
|
4
|
3690
|
|
POST
|
I have not seen this. A couple things to check out would be the error message - do you get any indication of why the sync fails? If not, then I would check the ArcGIS Server logs and see if you can get any hints from that. Otherwise, I suggest you log a support case to try and reproduce the issue with them. They should be able to assist you in troubleshooting, and if they can reproduce the issue, they can get a bug logged with us to fix. Thanks, Luke
... View more
07-31-2017
08:01 AM
|
0
|
0
|
1087
|
|
POST
|
Kai- I believe the issue is that you are creating the map programmatically in your application code, but the OfflineMapTask is designed to take a web map saved in ArcGIS Online/Portal and take all of its layers offline. Instead of building up the map programmatically, can you instead create the map in ArcGIS Online/Portal, and then try to take that offline? Thanks, Luke
... View more
07-31-2017
07:57 AM
|
0
|
0
|
3689
|
|
BLOG
|
Becca- Are you using AppStudio? If so, you will probably need to post in their space to be sure you know what version they are using. Otherwise, you should be able to go to the Qt Creator Preferences > Build and Run, and that will list all of the kits you have.
... View more
07-31-2017
07:08 AM
|
0
|
0
|
796
|
|
POST
|
As a workaround for now, you could create the renderer from JSON. An example workflow would be: 1) Create a WebMap in ArcGIS Online and configure the layer to have a heat map renderer 2) Open the Map in Runtime, iterate through the layers and find the one with the heat map renderer, and call toJson on it 3) Use that JSON (or a modified version of it) to construct a new Renderer by using fromJson, and set that renderer on a Feature Layer It'll probably take some trial and error but it might at least get you going for the time being
... View more
07-26-2017
12:27 PM
|
0
|
0
|
2985
|
|
POST
|
Hi Rainer, Version 100.x does not support static linking on Linux. Thanks, Luke
... View more
07-25-2017
08:31 AM
|
1
|
0
|
967
|
| Title | Kudos | Posted |
|---|---|---|
| 3 | 05-27-2026 09:52 AM | |
| 1 | 11-24-2025 10:45 AM | |
| 1 | 07-30-2025 08:26 AM | |
| 1 | 05-15-2025 07:35 AM | |
| 2 | 11-26-2024 01:27 PM |
| Online Status |
Offline
|
| Date Last Visited |
06-17-2026
07:54 AM
|