System functions

The AppStudio AppFramework contains several components that provide access to standard and well-known system functions. While these components are not required to use these functions in your app, implementing the components should be considered when planning to use these functions.

Clipboard

By default, there is nothing preventing an AppStudio app from accessing the cut, copy, and paste functions of the system clipboard, and you don't need to write any code if this is your intention. For more complex workflows involving the clipboard, including copying items such as colors and JavaScript objects, the Clipboard component provides more detailed access to the system clipboard.

The Clipboard component contains multiple properties and methods for returning the contents of the system clipboard, depending on the type of data stored in it. The text property returns the contents as a plain text string if possible, without formatting and potentially with visible HTML, depending on the clipboard contents.

TextArea {
    id: textArea
                    
    Layout.fillWidth: true
    Layout.fillHeight: true
                    
    text: AppFramework.clipboard.text
    readOnly: true
}

The html property, however, is primarily intended to read and display HTML content. This property is also capable of reading and retaining more complex text formatting, which the following code sample uses by attaching the property to a text area with rich text format enabled.

TextArea {
    id: htmlTextArea
                    
    Layout.fillWidth: true
    Layout.fillHeight: true
                    
    text: AppFramework.clipboard.html
    textFormat: Text.RichText
    readOnly: true
}

Color values are stored as an application/x-color MIME type and can only be written or returned by the color property.

The Clipboard component has no means to interact with images on the system clipboard (although, depending on the source, the text property may return a URL). Instead, the ImageObject component provides the copyFromClipboard and pasteFromClipboard methods for interaction.

Flow {
    Layout.fillWidth: true
            
    ImageObject {
        id: imageObject
    }
            
    Button {
        text: "Clear Image"
        enabled: !imageObject.empty
                
        onClicked: {
            imageObject.clear();
        }
    }
            
    Button {
        text: "Copy"
        enabled: !imageObject.empty
                
        onClicked: {
            imageObject.copyToClipboard();
        }
    }
            
    Button {
        text: "Paste"
        enabled: imageObject.canPasteFromClipboard
                
        onClicked: {
            imageObject.pasteFromClipboard();
        }
    }
}

Sharing functionality

You can share text, URLs, or files to other apps using sharing functionality provided by AppFramework Clipboard. The Clipboard component's share method is used to share any input text or URL. If sharing a file, the share method needs you to provide the file location URL. The following code snippet shows how to use this method, sharing the text entered into a text field.

property url shareURL

TextField {
    id: inputText
    placeholderText: "Enter something to share"
}

Button {
    text: "Share as text"

    onClicked: {
        AppFramework.clipboard.share(inputText.text)
    }
}

Button {
    text: "Share as Url"

    onClicked: {
        shareURL = inputText.text
        AppFramework.clipboard.share(shareURL)
    }
}

Currently, this functionality is only supported on macOS, iOS, and Android platforms.

For an example of this functionality in use, refer to the sample app available in ArcGIS AppStudio, or in the AppStudio samples GitHub repository.

Locale information

A locale is a standardized value describing a language or dialect, including details such as alphabet used, decimal markers, and date format. By using a valid locale code, you can override your system's default locale and provide a number of important ways information in your app will be displayed.

These locales can be passed on to the app through the use of the LocaleInfo component, which contains properties to define a locale, as well as to map the locale consistently across standards and other sections of your app. In AppStudio, an example is to use LocaleInfo to determine the language of an OAuth sign-in dialog box for ArcGIS Online. To do this, first instantiate LocaleInfo, and inform it of both the initial locale and when the locale changes.

property string localeName
property string oauthUrlFormat: "https://www.arcgis.com/sharing/rest/oauth2/authorize?client_id=arcgisonline&redirect_uri=http://www.arcgis.com&response_type=token&locale=%1"
property url oauthUrl
    
Component.onCompleted: {
    // Get the current Locale from the system's locale settings
    localeName = Qt.locale().name;
}

LocaleInfo {
    id: localeInfo
    name: localeName

    //  update the properties and the OAuth page when the app Locale is changed
    onLocaleChanged: {
        localeInfoModel.update(localeInfo);
        oauthUrl = oauthUrlFormat.arg(esriName);
        if (oauthTab.item) {
            oauthTab.item.url = oauthUrl;
        }
    }
}

To update the app's locale, add a text field to both display and edit the locale.

Text {
    text: "Locale search"
}

// locale Name provided by the user for the app e.g. fr-Fr, en-GB, de_DE
TextField {
    id: localeField
    Layout.fillWidth: true
    text: localeName
    placeholderText: "Locale"
    onEditingFinished: {
        localeName = text;
    }
    function update(name) {
        text = name;
        editingFinished();
    }
}

Since the other properties of LocaleInfo won't be updated during synchronization, a function is needed to update them. For the purposes of this workflow, the function will also be in a list model that can be exposed in the UI.

// Model to list the properties associated with the LocaleInfo
ListModel {
    id: localeInfoModel
    // function to update the properties when the Locale is changed in the textbox
    function update(localeInfo) {
        clear();
        add("name",                 localeInfo.name);
        add("ietfName",             localeInfo.ietfName);
        add("esriName",             localeInfo.esriName);
        add("languageName",         localeInfo.languageName);
        add("languageCode",         localeInfo.languageCode);
        add("countryName",          localeInfo.countryName);
        add("countryCode",          localeInfo.countryCode);
        add("scriptName",           localeInfo.scriptName);
        add("scriptCode",           localeInfo.scriptCode);
    }
    function add(name, value) {
        append({
            name: name,
            value: value.toString()
        });
    }
}

After the list model is set up, you can add a web view to an OAuth sign-in, which will display in the locale declared in the earlier text field. In this case, the web view displays as part of a tab view alongside the list of LocaleInfo properties above.

TabView {
    Layout.fillWidth: true
    Layout.fillHeight: true

    Tab {
        id: localeInfoTab
        title: "LocaleInfo"

        TableView {
            model: localeInfoModel

            TableViewColumn {
                role: "name"
                title: "Property"
            }

            TableViewColumn {
                role: "value"
                title: "Value"
            }
        }
    }

    Tab {
        id: oauthTab
        title: "Sign In Page"
        WebView {
            // Load the OAuth url in the webView.
            Component.onCompleted: {
                url = oauthUrl;
            }
        }
    }
}

Be aware that controlling the locale code and changing your app's presentation depending on it are only part of the localization process. For more information, see Globalize your app.

URLs

To perform complex operations with URLs, the UrlInfo component provides properties and methods for constructing and deconstructing URLs. These properties and methods can be used to dynamically construct a URL or derive individual components of one. The following section of code shows how to use UrlInfo to extract the parameters of a query from a URL, in this case a feature service. Edits made to the extracted query when the sample app is run are then reassembled and presented as a new URL.

Column {
    id: cl
    width: parent.width
    spacing: 5

    UrlInfo {
        id: urlInfo
    }

    Text {
        text: "Your initial URL:"
        wrapMode: Text.WrapAnywhere
        width: parent.width
    }

    TextArea {
        id: urlField
        selectByMouse: true
        cursorPosition: 1
        wrapMode: "Wrap"
        width: parent.width
        font.pixelSize: 10
        horizontalAlignment :TextInput.AlignLeft
        text:"https://csmgisweb.smgov.net/csmgis01/rest/services/admin_boundaries/zoning/MapServer/0/query?objectIds=99,100&time=&geometry=&geometryType=esriGeometryPoint&inSR=&spatialRel=esriSpatialRelContains&f=html"

        onTextChanged: {
            urlInfo.fromUserInput(text);
        }
    }

    CheckBox {
        text: "<b>Is a query present?</b>"
        checked: urlInfo.hasQuery
        enabled: false
        padding: 0
    }

    Text {
        text: "<b>The query for your URL</b>: "
        wrapMode: Text.WrapAnywhere
        width: parent.width
    }

    Text {
        text: "Edit the query, and the URL below it will update with your changes."
        wrapMode: Text.WrapAnywhere
        width: parent.width
    }

    TextArea {
        id: queryField
        text: JSON.stringify(urlInfo.queryParameters, undefined, 2)
        wrapMode: Text.WrapAnywhere
        width: parent.width

        onTextChanged: {
            urlInfo.queryParameters = JSON.parse(text);
        }
    }

    Text {
        text: "<b>Your URL with updated query:<b>"
        wrapMode: Text.WrapAnywhere
        width: parent.width
    }

    TextField {
        id: reQueried
        text: urlInfo.url
        wrapMode: Text.WrapAnywhere
        width: parent.width
    }
}