Qt-based BB10 API Examples Documentation

Contents

RSS News Example

Files:

Description

The RSS News example demonstrates how to extract display data RSS News feeds from the network.

Overview

In this example we'll learn how to use the DataSource class to load and parse JSON and XML files and use the extracted data.

The UI

The UI of this sample application consists of three screens. The first screen allows the user to choose between two news sources (Google and Yahoo) and shows the list of available feeds for the selected source. When the user selects on of the feeds, the second screen is presented, which shows all the articles of the selected feed in a ListView. Selecting one of the articles will bring up the third screen, which shows the content of the article in a WebView. Since all screens are put on a NavigationPane, the user can go back to the previous screen by clicking the 'Back' button.

The list of feeds for the two news sources are stored inside the two JSON files 'googlerssfeeds.json' and 'yahoorssfeeds.json', which are located inside the assets directory of the project. The actual articles are fetched from the network as soon as the user selects one of the feeds.

The central objects in this sample application are DataSource and GroupDataModel. We have two of the, one for the feeds and one for the articles.

    // The data model that contains the content of a JSON file
    GroupDataModel {
        id: feedsDataModel
        sortingKeys: ["order"]
        grouping: ItemGrouping.None
    },

    // The data source that fills the above model with the content of a JSON file
    DataSource {
        id: feedsDataSource
        source: ""
        onDataLoaded: {
            feedsDataModel.clear();
            feedsDataModel.insertList(data);
        }
        onError: {
            console.log("JSON Load Error: [" + errorType + "]: " + errorMessage);
        }
    },
    // The data model that contains the articles from a RSS feed
    GroupDataModel {
        id: articlesDataModel
        sortingKeys: ["pubDate"]
        sortedAscending: false
        grouping: ItemGrouping.None
    },

    // The data source that fills the above model with the articles
    DataSource {
        id: articlesDataSource
        source: ""
        query: "/rss/channel/item"
        type: DataSource.Xml
        onDataLoaded: {
            articlesDataModel.clear();
            articlesDataModel.insertList(data);
        }
        onError: {
            console.log("RSS Load Error[" + errorType + "]: " + errorMessage);
        }
    },

While DataSource is used to load and parse the data from a JSON or XML file, the GroupDataModel is used to store the parsed data inside and make them available to ListViews

    // A control to switch between the two news sources
    SegmentedControl {
        id: newsSources

        options: [
            Option {
                text: qsTr ("Google")
                value: "googlerssfeeds.json"
            },
            Option {
                text: qsTr ("Yahoo!")
                value: "yahoorssfeeds.json"
            }
        ]

        onSelectedOptionChanged: {
            if (selectedOption != 0) {
                feedsDataSource.source = selectedOption.value;
                feedsDataSource.load();
            }
        }

        onCreationCompleted: {
            if (selectedOption != 0) {
                feedsDataSource.source = selectedOption.value;
                feedsDataSource.load();
            }
        }
    }

If the user selects one of the news sources in the SegmentedControl, the 'source' property of the feedsDataSource is set to the corresponding JSON file. The feedsDataSource will now parse the JSON file and fill the data into the feedsDataModel.

    // A list view that shows all the categories of a news source
    ListView {
        dataModel: feedsDataModel

        listItemComponents: [
            ListItemComponent {
                type: "item"
                Container {
                    leftPadding: 30
                    preferredWidth: 768
                    preferredHeight: 100

                    layout: DockLayout {}

                    Label {
                        verticalAlignment: VerticalAlignment.Center

                        text: ListItemData.name

                        textStyle.base: SystemDefaults.TextStyles.TitleText
                        textStyle.color: Color.White
                    }

                    Divider {
                        verticalAlignment: VerticalAlignment.Bottom
                    }
                }
            }
        ]

        onTriggered: {
            var feedItem = feedsDataModel.data(indexPath);
            articlesDataSource.source = "http://" + feedItem.feed;
            articlesDataSource.load();

            var page = newsListings.createObject();
            page.title = newsSources.selectedOption.text + ": " + feedItem.name
            navPane.push(page);
        }
    }

The feedsDataModel is used inside a ListView on the first screen and whenever the user selects one of the items, the HTTP URL for the selected feed is assembled and set on the 'source' property of the articlesDataSource object. Now the articlesDataSource object will load the XML file from the network and extract all XML elements that match the given XPath query '/rss/channel/item'. When this is done it will store the articles into the articlesDataModel object.

Additionally to loading the articles, clicking on a feed also pushes a new screen on the NavigationPane. This is done by creating a new object of a ComponentDefinition for that screen.

    // The dynamically loaded page to show the list of articles from a RSS feed
    ComponentDefinition {
        id: newsListings
        Page {
            property alias title : titleLabel.text

            Container {
                layout: DockLayout {}

                ImageView {
                    horizontalAlignment: HorizontalAlignment.Fill
                    verticalAlignment: VerticalAlignment.Fill

                    imageSource: "asset:///images/background.png"
                }

                Container {
                    Container {
                        horizontalAlignment: HorizontalAlignment.Center
                        layout: DockLayout {}

                        ImageView {
                            horizontalAlignment: HorizontalAlignment.Fill
                            verticalAlignment: VerticalAlignment.Fill

                            imageSource: "asset:///images/header_background.png"
                        }

                        Label {
                            id: titleLabel

                            horizontalAlignment: HorizontalAlignment.Center

                            textStyle.base: SystemDefaults.TextStyles.BigText
                            textStyle.color: Color.create("#bbffffff")
                        }
                    }

                    ListView {
                        dataModel: articlesDataModel
                        listItemComponents: [
                            ListItemComponent {
                                type: "item"
                                ArticleItem {
                                    title: ListItemData.title
                                    pubDate: ListItemData.pubDate
                                }
                            }
                        ]
                        onTriggered: {
                            var feedItem = articlesDataModel.data(indexPath);

                            var page = detailPage.createObject();
                            page.htmlContent = feedItem.description;
                            navPane.push(page);
                        }
                    }
                }
            }
        }
    },

The screen contains a ListView that works on the articlesDataModel. Whenever the user selects an article, the third screen (that contains a WebView) is pushed on the NavigationPane, and the 'html' property of the WebView is set to the content of the selected article.

    // The dynamically loaded page to show an article in a webview
    ComponentDefinition {
        id: detailPage
        Page {
            property alias htmlContent: detailView.html

            Container {
                ScrollView {
                    scrollViewProperties.scrollMode: ScrollMode.Vertical

                    WebView {
                        id: detailView;
                    }
                }
            }
        }
    }