Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for Qt

Show organization basemaps

Sample Viewer View Sample on GitHub

Connect to Portal to give users access to their organization's basemaps.

Use case

Organizational basemaps are a Portal feature allowing organizations to specify basemaps for use throughout the organization. Customers expect that they will have access to their organization's standard basemap set when they connect to a Portal. Organizational basemaps are useful when certain basemaps are particularly relevant to the organization, or if the organization wants to make premium basemap content available to their workers.

How to use the sample

You'll be prompted to provide a URL to your Portal, then sign in. After you sign in, you'll see a map and a list of basemaps to choose from. Select a basemap to use it in the map.

How it works

  1. The user is prompted to load a portal anonymously or with a log-in.
  2. A Portal is then loaded - if the user chose to log-in in step 1, this uses a Credential of type OAuth.
  3. When the app starts, the portal is loaded and if required, the AuthenticationManager issues a challenge for the supplied credential type.
  4. The user is presented with an AuthenticationView which allows them to log-in.
  5. After a successful load, a request is made to fetchBasemaps from the portal instance.
  6. When the basemaps are successfully retrieved, the portal's BasemapListModel is passed to a QML GridView.
  7. A delegate shows each basemap's title and thumbnail image.
  8. When the user double-clicks on a Basemap in the list, a Map is created using this (unloaded) item.
  9. The map is then loaded and once the operation is complete it is set on a MapView to show the user's selected basemap.
  10. A back button allows the user to return to the list of basemaps.

Relevant API

  • AuthenticationManager
  • BasemapListModel
  • Credential
  • Portal

Additional information

See Customize basemaps in the Portal for ArcGIS documentation to learn about customizing the organization's basemap list in a portal.

Tags

basemap, integration, organization, portal

Sample Code

import QtQuick 2.6
import QtQuick.Controls 2.2
import Esri.ArcGISRuntime 100.9
import Esri.ArcGISRuntime.Toolkit.Dialogs 100.9

Rectangle {
    id: rootRectangle
    clip: true
    width: 800
    height: 600
    
    property var porInfo: portal.portalInfo

    function chooseBasemap(selectedBasemap) {
        title.text = selectedBasemap.item.title;
        basemapsGrid.enabled = false;

        const newMap = ArcGISRuntimeEnvironment.createObject("Map", {item: selectedBasemap.item});
        mapView.map = newMap;
        gridFadeOut.running = true;
        mapView.visible = true;
    }

    BusyIndicator {
        anchors.centerIn: parent
        running: !anonymousLogIn.visible && !mapView.visible && portal.loadStatus !== Enums.LoadStatusLoaded;
    }

    Credential {
        id: oAuthCredential
        oAuthClientInfo: OAuthClientInfo {
            oAuthMode: Enums.OAuthModeUser
            clientId: "iLkGIj0nX8A4EJda"
        }
    }

    Portal {
        id: portal

        //! [Portal fetchBasemaps after loaded]
        onLoadStatusChanged: {
            if (loadStatus === Enums.LoadStatusFailedToLoad) {
                retryLoad();
                return;
            }

            if (loadStatus !== Enums.LoadStatusLoaded)
                return;

            fetchBasemaps();
        }

        onFetchBasemapsStatusChanged: {
            if (fetchBasemapsStatus !== Enums.TaskStatusCompleted)
                return;

            basemapsGrid.model = basemaps;
            gridFadeIn.running = true;
        }
        //! [Portal fetchBasemaps after loaded]
    }

    Text{
        id: title
        anchors {
            top: parent.top;
            left: parent.left;
            right: parent.right;
            margins: 10
        }
        font.pointSize: 14
        font.bold: true
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignTop
        text: anonymousLogIn.visible ? "Load Portal" :
                                       (basemapsGrid.count > 0 ? porInfo.organizationName + " Basemaps" : "Loading Organization Basemaps...")
        wrapMode: Text.Wrap
        elide: Text.ElideRight
    }

    MapView {
        id: mapView
        anchors {
            top: title.bottom;
            bottom: parent.bottom;
            left: parent.left;
            right: parent.right
        }
        visible: false
    }

    Button {
        id: backButton
        anchors {
            top: mapView.top
            right: mapView.right
            margins: 16
        }
        visible: mapView.visible
        icon.source: "qrc:/Samples/CloudAndPortal/ShowOrgBasemaps/ic_menu_back_dark.png"
        text: "Back"
        opacity: hovered ? 1 : 0.5

        onClicked: {
            title.text = "Basemaps";
            mapView.visible = false;
            basemapsGrid.enabled = true;
            gridFadeIn.running = true;
        }
    }

    GridView {
        id: basemapsGrid
        anchors {
            top: title.bottom;
            bottom: parent.bottom;
            left: parent.left;
            right: parent.right
        }
        cellWidth: 128;
        cellHeight: 128
        opacity: 0
        focus: true
        clip: true

        delegate: Rectangle {
            anchors.margins: 5
            width: basemapsGrid.cellWidth
            height: width
            border {
                width: 2;
                color: index === basemapsGrid.currentIndex ? "blue" : "lightgrey"
            }
            color: index === basemapsGrid.currentIndex ? "yellow" : "white"
            radius: 2
            clip: true

            //! [BasemapListModel example QML delegate]
            Image {
                id: basemapImg
                anchors {
                    bottom: basemapLabel.top;
                    horizontalCenter: parent.horizontalCenter
                }
                height: parent.height - ( basemapLabel.height * 2 );
                width: height
                source: thumbnailUrl
                fillMode: Image.PreserveAspectCrop
            }

            Text {
                id: basemapLabel
                anchors {
                    bottom: parent.bottom;
                    left: parent.left;
                    right: parent.right
                }
                height: 16
                z: 100
                horizontalAlignment: Text.AlignHCenter
                text: title
                wrapMode: Text.Wrap
                elide: Text.ElideRight
                font.pointSize: 8
                font.bold: index === basemapsGrid.currentIndex
            }
            //! [BasemapListModel example QML delegate]

            MouseArea {
                enabled: !mapView.visible && portal.loadStatus === Enums.LoadStatusLoaded
                anchors.fill: parent

                onClicked: {
                    if (!enabled)
                        return;

                    basemapsGrid.currentIndex = index;
                }

                onDoubleClicked: {
                    if (!enabled)
                        return;

                    selectedAnimation.running = true;
                    chooseBasemap(basemapsGrid.model.get(index));
                }
            }

            SequentialAnimation on opacity {
                id: selectedAnimation
                running: false
                loops: 4
                PropertyAnimation { to: 0; duration: 60 }
                PropertyAnimation { to: 1; duration: 60 }
            }
        }

        OpacityAnimator on opacity {
            id: gridFadeIn
            from: 0;
            to: 1;
            duration: 2000
            running: false
        }

        OpacityAnimator on opacity {
            id: gridFadeOut
            from: 1;
            to: 0;
            duration: 2000
            running: false
        }
    }

    Button {
        id: anonymousLogIn
        anchors {
            margins: 16
            horizontalCenter: parent.horizontalCenter
            top: title.bottom
        }
        text: "Anonymous"
        icon.source: "qrc:/Samples/CloudAndPortal/ShowOrgBasemaps/ic_menu_help_dark.png"

        onClicked: {
            portal.load();
            anonymousLogIn.visible = false;
            userLogIn.visible = false;
        }
    }

    Button {
        id: userLogIn
        anchors {
            margins: 16
            horizontalCenter: anonymousLogIn.horizontalCenter
            top: anonymousLogIn.bottom
        }
        width: anonymousLogIn.width
        text: "Sign-in"
        icon.source: "qrc:/Samples/CloudAndPortal/ShowOrgBasemaps/ic_menu_account_dark.png"

        onClicked: {
            portal.credential = oAuthCredential;
            portal.load();
            anonymousLogIn.visible = false;
            userLogIn.visible = false;
        }
    }

    /*
    // Uncomment this section when running as standalone application
    AuthenticationView {
        authenticationManager: AuthenticationManager
    }
    */
}