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;
                            }
                        }
                    }
                }
            }