Thursday, January 17, 2013

Informative list views in Cascades (BB10)

This post gives an example how you can present the user some informative text or controls when a list view is empty.

Typical scenarios where this may be desirable are:
  • When populating a list view with data from a network service.
    • Show a Fetch data button if the list view is empty.
    • Present any error that might occur while downloading/processing the data
  • Showing search result in a list view.
    • Present a No items found text to the user if the list view is empty.
In the example application I'm using an ArrayDataModel, but it should work for QListDataModel and GroupDataModel too. Unfortunately, it will not work with XmlDataModel because the class doesn't expose any function to query if the model is empty (at least not easily).

All of the data models mentioned above provides an isEmpty() function which can be used to check if the data model contain any items or not.

The example should speaks for itself, so without any further ado, here's the code:

import bb.cascades 1.0
Page {

    Container {
        layout: DockLayout {}

        ListView {
            dataModel: ArrayDataModel {
                id: model

                // Bindable property which tells if the
                // model is empty or not
                property bool empty: true

                // Populates model with dummy data
                function populate() {
                    for (var i = 0; i < 10; i++) {
                        append({'title' : 'Item #' + i})
                    }
                }

                // The following signal handlers updates
                // the empty property to correct state
                onItemAdded: empty = isEmpty()
                onItemRemoved: empty = isEmpty()
                onItemUpdated: empty = isEmpty()

                // You might see an 'unknown signal' error
                // in the QML-editor, guess it's a SDK bug.
                onItemsChanged: empty = isEmpty()
            }
        }

        // Only visible when data model is empty.
        // This should be declared after the ListView
        // to prevent the ListView from consuming touch input etc
        // Setting ListView's visible property to !model.empty will
        // also work.
        Label {
            visible: model.empty //model.isEmpty() will not work
            horizontalAlignment: HorizontalAlignment.Fill
            verticalAlignment: VerticalAlignment.Center

            text: qsTr("No entries yet\n\nPlease populate data model")
            textStyle.base: SystemDefaults.TextStyles.BigText
            textStyle.textAlign: TextAlign.Center
            multiline: true
        }

    }

    actions: [
        // Action to populate/clear data model depending on state.
        // Same here, model.isEmpty() will not behave as expected.
        ActionItem {
            title: model.empty ? qsTr("Populate") : qsTr("Clear")
            onTriggered: model.empty ? model.populate() : model.clear()
            ActionBar.placement: ActionBarPlacement.OnBar
        }
    ]
}


Screenshots from the example application

A work-around is required because isEmpty() is only an invokable function in QML, and not a bindable property. The example will not behave as expected if model.isEmpty() is set as a value for the Label's visible property. The isEmpty() function is only called once when the Label is created and will never be re-evaluated again since it's not a bindable property (hint to Cascades API developers).

Please feel free to add other ways to accomplish this in the comments section.

Friday, November 23, 2012

More guest posts at devblog.blackberry.com

Forgot to mention that I've posted two more posts at BlackBerry DevBlog a while ago.
The target audience are new comers to QML.

Tuesday, June 26, 2012

Python and Qt on BlackBerry [PlayBook]

I've just bought a BlackBerry PlayBook. After been spending some time with a borrowed PlayBook I decided to buy one myself. Many of you might wonder why the hell I did that but I really think it's a great device. The three top things that made me buy the PlayBook are:
  • Cheap! Good value for the money, the 32 Gb version for only €249
  • Awesome user experience. Really love those swipe gestures which only requires one finger so you can pretty much operate the device with only one finger :). It also gets addictive!
  • It runs Qt and Python!
You might argue that there are very little apps for the PlayBook but admittedly I mostly use the browser so that isn't such a big deal for me. The native PIM-apps integrates well with Google services, such as mail, calendar and contacts. The only thing that I'm missing is an official twitter client. There're a bunch of them on AppWorld but I haven't had time to checked them out yet. RIM do also claim that the PlayBook will be upgradeable to BlackBerry 10 so that should give some confidence of the PlayBook having an upgrade path :)

The PlayBook is powered by QNX which is a real-time micro kernel and supports a lot of POSIX APIs. This basically means that many open source apps/libs for Linux can be ported with little or no effort. What I think is rather cool is that Python 3.2 is pre-installed on the PlayBook which you can use to run Python application.

BlackBerry-Py is a project which goal is to build an environment to support application development in Python for the PlayBook and the upcoming BlackBerry 10 OS. BB-Py uses PySide (Python bindings for Qt) for the UI and the project is also working on support for Cascades. It's very easy to get started so I'll just point you to the "Hello World" example which describes every step you need to take to deploy an app to the device. And no, I didn't find it that hard to get the debug token which you need to install your app on the device :).

Currently the PlayBook OS doesn't include the Qt libraries so they, and PySide, need to be bundled with your app. BB10 is using Qt to a great extent (Cascades is built on top of Qt) and the libraries will be available on the filesystem, only PySide needs to be bundled.

Oh, you also need to download an SDK, for example the Native SDK, to get the required tools for packaging and deploying.