Files:
The RSS News example demonstrates how to extract display data RSS News feeds from the network.
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 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; } } } } }