Skip navigation
All Places > AppStudio for ArcGIS > Blog > 2017 > August
2017

We are excited to announce the release of five brand new beautiful material design layouts.  These ready-to-use layouts will not only help you get started in creating material design apps with AppStudio but also get you familiarized with the latest Qt Material Control style.  You can find these layouts in the AppStudio Desktop Edition.

 

What’s Material Design

Material design, which takes inspiration from the study of paper and ink, is a visual and interactive card-based design tool that was announced by Google in 2014.  Google’s initiative is to develop a much cleaner and more colorful unified user experience that can be adapted across different platforms and different device sizes.  Many Google applications were revamped to follow the material design principles (such as Gmail, Google Drive, Google Calendar, YouTube, etc.).

 

Material Styles

The new Qt Quick Controls 2.0 comes with three styles: Default, Material, and Universal.  We added support for Material Style, which is based on the Material Design Guidelines, and Universal Style, which is based on the Microsoft Universal Design Guidelines in the AppStudio for ArcGIS 2.0 release.  The material style is not a native Android style; it is a cross-platform control style that runs on any platform.  You may have noticed that one of the AppStudio templates, the Map Viewer template app, has been updated to the material design standard.

 

New Material Design Layouts

We released five brand-new material design layouts to help you get started with implementing the material design in your apps.

 

Simple Layout (Material Design)

 

This is a one-page simple layout with a header and a floating action button on it.  When you tap the floating action button, a dialog will pop up with the message “Welcome to AppStudio” on it.

 

 

 

Multipage Layout (Material Design)

 

This is a multiple page layout using a StackView QML type demonstrates how to navigate between different pages in your app. You can press the button to go to the next page and press the back icon on the header to go back to the previous page.

 

 

Side Menu Layout (Material Design)

 

The side menu layout is one of the most demanding and popular layouts. When you hit the menu icon on the top right, a navigation drawer slides in from the left with all of the navigation options on it. You can find this layout in many popular apps such as Twitter, Gmail, and Uber.

 

 

Tab Layout (Material Design)

 

This tab layout is extremely useful when there are multiple tabs in a page.  When you hit different tabs, the corresponding item shows up on the page.

 

 

Onboarding Layout (Material Design)

 

The onboarding is the very first thing you see after downloading an app.  Onboarding screens introduce you to the app and demonstrate how to use the app. SwipeView QML Type is used in this layout to navigate between different pages by swiping.

 

 

             

   

 

How to Get Material Design Layouts

  1. Open AppStudio Desktop
  2. Click on the New App Button
  3. Click on the Layouts tab
  4. Select the Layout and click on the Create button

 

 

You can also create your own material design app without using material design layout.  All you need to do is add the import statement when creating a new app.  

 

import QtQuick.Controls.Material 2.1

  

I hope you are as excited as we are about the new material design layouts. Now it is your turn to create some awesome apps with the material design style.

 

Summary

 

This is the second blog about the SQL Beta feature in AppStudio 2.0. If you haven't seen the first blog, I recommend you start there.

 

In this blog, we will discuss SQLite In-Memory databases and CSV files and how this may benefit your application.

 

1. SQLite In-Memory Database

 

The ":memory:" name is used to specify the in-memory database. This is useful for applications that would like to start with a blank SQLite database every time the application is run and do not need the data to persist after the application has completed. This is useful for providing model content to populate controls.

 

import QtQuick 2.7
import QtQuick.Controls 2.1
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Sql 1.0

App {
    id: app
    width: 640 * AppFramework.displayScaleFactor
    height: 480 * AppFramework.displayScaleFactor

    ComboBox {
        id: countryComboBox
        readonly property var _model: model
        textRole: "country"
    }

    SqlDatabase {
        id: db
        databaseName: ":memory:"
    }

    Component.onCompleted: {
        db.open();
        db.query("CREATE TABLE world_cities (name TEXT,subcountry TEXT, country TEXT)");
        db.query("INSERT INTO world_cities VALUES ('Melbourne', 'Victoria', 'Australia')");
        db.query("INSERT INTO world_cities VALUES ('Redlands', 'California', 'United States')");
        countryComboBox.model = db.queryModel('SELECT DISTINCT country FROM world_cities');
    }
}

 

2. Bundling CSV files in your app

 

If you have data in a CSV file, we can create a linked table in SQLite. As a linked table only the metadata, i.e. filename to the CSV file is stored in SQLite, the content will continue to reside only in the CSV file. The CSV file can be either a physical file or an embedded resource. The syntax to linking tables is as follows:

 

CREATE VIRTUAL TABLE tableName USING CSV ( 'filePath' )

 

The advantage of using technique is that you will have access to your CSV data via the SQLite query engine.

 

When we're developing the application we will be using:

 

CREATE VIRTUAL TABLE world_cities USING CSV ( 'C:/Users/Stephen/ArcGIS/AppStudio/Apps/Sample/data/world-cities.csv' )

 

When we've finalized the application and want to build it using Local Make or Cloud Make, we want to change it to:

 

CREATE VIRTUAL TABLE world_cities USING CSV ( ':/qml/data/world-cities.csv' )

 

To achieve both we will use the FileFolder object to help.

 

    SqlDatabase {
        id: db
        databaseName: ":memory:"
    }

    FileFolder {
        id: dataFolder
        url: "data"
    }

    Component.onCompleted: {
        var csvFilePath = dataFolder.filePath("world-cities.csv");
        db.open();
        db.query("CREATE VIRTUAL TABLE world_cities USING CSV ( '" + csvFilePath + "' )");
        countryComboBox.model = db.queryModel('SELECT DISTINCT country FROM world_cities');
    }

 

3. ComboBox with Huge Data

 

By leveraging from the SQLite query engine we can build quite compelling user interfaces quickly and simply. In the following example, instead of asking the user to select from a list of 20,000 cities, we can filter the list with a WHERE clause on country and subcountry.

 

 

    cityComboBox.model = db.queryModel(
          "SELECT    name "
        + "FROM      world_cities "
        + "WHERE     country = :country "
        + "AND       subcountry = :subcountry "
        + "ORDER BY  name",
          {
              country: countryComboBox.currentText,
              subcountry: subcountryComboBox.currentText
          }
    );

 

If you are experiencing a lag whenever the queries are run, then, at this point, you will need to consider using SQLite indexes. However, indexes cannot be applied to the linked table. We must make a copy of the table and then we can put indexes on the copy.

 

    Component.onCompleted: {
        var csvFilePath = dataFolder.filePath("world-cities.csv");
        db.open();
        db.query("CREATE VIRTUAL TABLE world_cities_csv USING CSV ('" + csvFilePath + "')");
        db.query("CREATE TABLE world_cities AS SELECT * FROM world_cities_csv");
        db.query("CREATE INDEX IX_world_cities_001 ON world_cities (country, subcountry, name)");
        countryComboBox.model = db.queryModel('SELECT DISTINCT country FROM world_cities');
    }

 

4. Known Issues

 

4.1. Garbage Collection on Models

 

The Javascript garbage collector is prematurely destroying models. For example, the pattern for assigning a query model to a QML component is as follows:

 

        countryComboBox.model = db.queryModel(

 

QML components, currently, do not inform the Javascript garbage collector that it has a reference to the model. The Javascript garbage collector *CAN* destroy the model whenever it feels like. This can lead to instability with the QML component. i.e. suddenly the values in the ComboBox may disappear (i.e. be replaced with blanks instead of values) or interacting with the ComboBox may crash the application.

 

A workaround is to define a Javascript property that keeps the model alive. This is the purpose of the readonly _model property in the following code snippet:

 

    ComboBox {
        id: countryComboBox
        readonly property var _model: model
        textRole: "country"
    }

 

We've informed Qt company of this issue.

 

4.2 Quoted values

 

If you have quoted values in your CSV file, the values aren't unquoted when you access them. The workaround is you have to add additional logic to identify and remove the extraneous quotes.

 

This issue is being addressed for the next release of AppStudio

 

4.3 Trailing spaces aren't being trimmed

 

If you have trailing spaces in your CSV, e.g. "country, subcountry" instead of "country,subcountry" then this will cause a problem. For the time being, you will have to trim the trailing spaces from your CSV file.

 

This issue is being addressed for the next release of AppStudio

 

5. Select City sample

 

The "Select City from CSV" app is available for you to try which demonstrates all of the above points. You can find "Select City from CSV" app in AppStudio.

 

  1. Launch AppStudio
  2. Select New App
  3. Click Search Icon
  4. Type: Select City from CSV

 

                                                  

 

The "Select City from CSV" source code is also available at arcgis-appstudio-samples GitHub

 

6. Other AppStudio SQL Blogs

 

Introduction to SQL Beta in AppStudio 2.0

Using CSV files in your application