3 @author: Sudheer K. <scifi1947 at gmail.com>
4 @license: GNU General Public License
8 import "Library" as Library
15 id: stockDetailsScreen
16 property int componentWidth: width
17 property int itemHeight: 50
18 property string symbol: "YHOO"
19 property string stockName: ""
20 property string lastTradedPrice: ""
21 property string lastTradedDateTime: ""
22 property string change: ""
23 property string changePercentage: ""
24 property string daysRange: ""
25 property string yearRange: ""
26 property string marketVolume: ""
27 property string prevClose: ""
28 property string marketCap: ""
29 property string baseChartURL: "http://chart.finance.yahoo.com/z?q=&l=&z=m&p=s&a=v&p=s&lang=en-US®ion=US"
30 property string chartURL: ""
31 property string rssURL: ""
32 property string orientation: "Portrait"
34 property int currentScreenIndex: 1
36 signal logRequest(string strMessage)
37 signal loadChart(string duration)
44 Library.CustomGestureArea {
46 onSwipeLeft: detailsRect.switchScreen()
47 onSwipeRight: detailsRect.switchScreen()
50 Component.onCompleted: {
54 chartURL = baseChartURL+"&t=1d&s="+symbol;
58 function switchScreen(){
59 switch (currentScreenIndex){
61 stockDetailsLoader.sourceComponent = (stockDetailsScreen.width > stockDetailsScreen.height)? stockChartComponentLandscape : stockChartComponentPortrait;
62 currentScreenIndex = currentScreenIndex + 1;
65 stockDetailsLoader.sourceComponent = stockDetailsComponent;
66 currentScreenIndex = currentScreenIndex - 1;
71 logRequest("currentScreenIndex = "+currentScreenIndex);
74 function loadDetails(){
75 var queryURL = 'http://query.yahooapis.com/v1/public/yql?q=select Symbol,Name,LastTradePriceOnly,LastTradeDate,LastTradeTime,Change,ChangeinPercent,DaysRange,YearRange,Volume,PreviousClose,MarketCapitalization from yahoo.finance.quotes where symbol in ("'+symbol+'")&env=store://datatables.org/alltableswithkeys';
76 logRequest("Loading stock details from "+queryURL);
77 var response = new XMLHttpRequest();
78 response.onreadystatechange = function() {
79 if (response.readyState == XMLHttpRequest.DONE) {
80 refreshDetails(response.responseXML);
84 response.open("GET", queryURL);
89 rssURL = "http://feeds.finance.yahoo.com/rss/2.0/headline?region=US&lang=en-US&s="+symbol;
90 logRequest("Loading news from "+rssURL);
91 var response = new XMLHttpRequest();
92 response.onreadystatechange = function() {
93 if (response.readyState == XMLHttpRequest.DONE) {
94 refreshNewsModel(response.responseXML);
98 response.open("GET", rssURL);
102 function refreshDetails(responseXML){
103 if (!responseXML) return;
104 var xmlDoc = responseXML.documentElement;
105 var results = xmlDoc.firstChild;
108 var quoteNodes = results.childNodes;
110 if (quoteNodes.length === 0) {
111 logRequest("No results for stock quote details");
114 //We are only expecting one quote node per symbol.
115 var quoteElements = quoteNodes[0].childNodes;
117 var lastTradedDate = "", lastTradedTime ="";
118 for (j = 0; j < quoteElements.length; j++){
120 if (quoteElements[j].childNodes[0]) {
121 switch (quoteElements[j].nodeName){
123 stockName = quoteElements[j].childNodes[0].nodeValue;
125 case 'LastTradePriceOnly':
126 lastTradedPrice = quoteElements[j].childNodes[0].nodeValue;
128 case 'LastTradeDate':
129 lastTradedDate = quoteElements[j].childNodes[0].nodeValue;
131 case 'LastTradeTime':
132 lastTradedTime = quoteElements[j].childNodes[0].nodeValue;
135 change = quoteElements[j].childNodes[0].nodeValue;
137 case 'ChangeinPercent':
138 changePercentage = quoteElements[j].childNodes[0].nodeValue;
141 daysRange = quoteElements[j].childNodes[0].nodeValue;
144 yearRange = quoteElements[j].childNodes[0].nodeValue;
147 marketVolume = quoteElements[j].childNodes[0].nodeValue;
149 case 'PreviousClose':
150 prevClose = quoteElements[j].childNodes[0].nodeValue;
152 case 'MarketCapitalization':
153 marketCap = quoteElements[j].childNodes[0].nodeValue;
159 if (lastTradedDate !== "") lastTradedDateTime = lastTradedDate + " " + lastTradedTime;
165 function refreshNewsModel(responseXML){
166 if (!(responseXML && stockNewsDataModel)) return;
168 var xmlDoc = responseXML.documentElement;
169 var channel = xmlDoc.firstChild;
171 //Not the best code I ever wrote, but got no choice
172 //Refer to Memory leak issue with XMLListModel --> http://bugreports.qt.nokia.com/browse/QTBUG-15191
175 var itemNodes = channel.childNodes;
178 logRequest("Clearing News Model");
179 stockNewsDataModel.clear();
182 for (i = 0; i < itemNodes.length; i++) {
184 if (itemNodes[i].nodeName === 'item'){
185 var newsElements = itemNodes[i].childNodes;
187 var newsTitle,newsLink
188 for (j = 0; j < newsElements.length; j++){
190 switch (newsElements[j].nodeName){
192 newsTitle = newsElements[j].childNodes[0].nodeValue;
195 newsLink = newsElements[j].childNodes[0].nodeValue;
200 stockNewsDataModel.append({"title":newsTitle,"link":newsLink});
208 id: stockNewsDataModel
212 id: stockNewsDelegate
215 id: newsWrapper; width: stockDetailsLoader.width; height: itemHeight
218 Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: newsWrapper.height - 2; width: newsWrapper.width; y: 1 }
220 anchors {verticalCenter: parent.verticalCenter;left: parent.left;leftMargin: 10;right: parent.right}
221 text: title; font.pixelSize: 14
223 verticalAlignment: Text.AlignVCenter
224 horizontalAlignment: Text.AlignLeft
225 elide: Text.ElideRight;
230 Library.CustomGestureArea {
233 logRequest("Opening news article: "+link);
234 Qt.openUrlExternally(link);
236 onSwipeLeft: detailsRect.switchScreen()
237 onSwipeRight: detailsRect.switchScreen()
244 id: stockDetailsComponent
251 anchors.top: parent.top
253 anchors.horizontalCenter: parent.horizontalCenter
255 horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter
256 font.pixelSize: 18; font.bold: true; elide: Text.ElideMiddle; color: "#B8B8B8"; style: Text.Raised; styleColor: "black"
257 text: (stockName != "")? (stockName +" ("+symbol+")"):symbol
262 id: stockDetailsSection
264 border.color: "#BFBFBF"
266 anchors {top: stockNameLabel.bottom;left: parent.left;right: parent.right}
271 id: stockDetailsColumn
272 anchors {top: parent.top; left: parent.left; leftMargin: 10}
276 label1: "Last Traded"
277 value1: lastTradedPrice
278 cell1Width: stockDetailsColumn.width/2
280 label2: "Day's Range"
282 cell2Width: stockDetailsColumn.width/2
286 label1: "Last Trade Time"
287 value1: lastTradedDateTime
288 cell1Width: stockDetailsColumn.width/2
292 cell2Width: stockDetailsColumn.width/2
297 value1: ((change != "" && changePercentage != "")? change + " ("+changePercentage+")":"")
298 cell1Width: stockDetailsColumn.width/2
302 cell2Width: stockDetailsColumn.width/2
306 label1: "Prev. Close"
308 cell1Width: stockDetailsColumn.width/2
312 cell2Width: stockDetailsColumn.width/2
319 border.color: "#BFBFBF"
322 anchors {top: stockDetailsSection.bottom;topMargin: 5;
323 bottom: parent.bottom;
327 flickDeceleration: 500
329 model: stockNewsDataModel
330 delegate: stockNewsDelegate
332 snapMode: ListView.SnapToItem
340 id: stockDetailsLoader
341 anchors{top: parent.top; bottom: parent.bottom; bottomMargin: 20;
342 left: parent.left; leftMargin: 10
343 right: parent.right; rightMargin: 10}
344 sourceComponent: stockDetailsComponent
347 target: stockDetailsScreen
348 onOrientationChanged: {
349 logRequest("Orientation Changed");
350 logRequest("New orientation is "+stockDetailsScreen.orientation);
351 logRequest("Margins for StockDetailsLoader are "+stockDetailsLoader.anchors.leftMargin+", "+stockDetailsLoader.anchors.rightMargin);
353 if (currentScreenIndex === 2){
354 if (stockDetailsScreen.orientation == "Landscape")
355 stockDetailsLoader.sourceComponent = stockChartComponentLandscape;
357 stockDetailsLoader.sourceComponent = stockChartComponentPortrait;
369 anchors.top: stockDetailsLoader.bottom
373 text: "Swipe horizontally to switch between details and charts."
374 horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
375 width: parent.width; font.pixelSize: 12; elide: Text.ElideRight;
377 style: Text.Raised; styleColor: "black"
381 id: footerMessageTimer
385 footerMessage.text = "";
389 Component.onCompleted: {
390 footerMessageTimer.start();
395 id: stockChartComponentLandscape
398 id: chartAreaWrapperLand
404 border.color: "#BFBFBF"
407 anchors { top: parent.top;topMargin: 40;
408 bottom: parent.bottom; bottomMargin: 20;
409 left: parent.left; right: parent.right}
412 Library.Loading { anchors.centerIn: parent; visible: chartImg.status == Image.Loading}
416 anchors {left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter}
418 sourceSize.width: 512
419 sourceSize.height: 288
421 fillMode: Image.PreserveAspectFit
425 logRequest("Image is ready");
428 logRequest("Image is loading");
431 logRequest("Image loading failed");
434 logRequest("No image specified");
441 target: stockDetailsScreen
443 chartURL = baseChartURL+"&t="+duration+"&s="+symbol;
444 logRequest(chartURL);
452 anchors {top: parent.top; topMargin: 40; bottom: parent.bottom;
453 right: chartAreaLand.right;rightMargin: 10}
458 anchors.horizontalCenter: parent.horizontalCenter
461 anchors { verticalCenter: parent.verticalCenter}
462 width: 50; height: 32
463 onClicked: loadChart("1d");
468 anchors { verticalCenter: parent.verticalCenter}
469 width: 50; height: 32
470 onClicked: loadChart("5d");
477 anchors.horizontalCenter: parent.horizontalCenter
480 anchors { verticalCenter: parent.verticalCenter}
481 width: 50; height: 32
482 onClicked: loadChart("3m");
487 anchors { verticalCenter: parent.verticalCenter}
488 width: 50; height: 32
489 onClicked: loadChart("6m");
495 anchors.horizontalCenter: parent.horizontalCenter
498 anchors { verticalCenter: parent.verticalCenter}
499 width: 50; height: 32
500 onClicked: loadChart("1y");
505 anchors { verticalCenter: parent.verticalCenter}
506 width: 50; height: 32
507 onClicked: loadChart("2y");
513 anchors.horizontalCenter: parent.horizontalCenter
516 anchors { verticalCenter: parent.verticalCenter}
517 width: 50; height: 32
518 onClicked: loadChart("5y");
523 anchors { verticalCenter: parent.verticalCenter}
524 width: 50; height: 32
525 onClicked: loadChart("my");
534 id: stockChartComponentPortrait
537 id: chartAreaWrapperPort
543 border.color: "#BFBFBF"
546 anchors { top: parent.top;topMargin: 40;
547 bottom: parent.bottom; bottomMargin: 20;
548 left: parent.left; right: parent.right}
551 Library.Loading { anchors.centerIn: parent; visible: chartImgPort.status == Image.Loading}
555 //anchors {left: parent.left; leftMargin: 10; horizontalCenter: parent.horizontalCenter}
556 anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 40}
558 sourceSize.width: 512
559 sourceSize.height: 288
561 fillMode: Image.PreserveAspectFit
562 width: parent.width - 20
566 logRequest("Image is ready");
569 logRequest("Image is loading");
572 logRequest("Image loading failed");
575 logRequest("No image specified");
582 target: stockDetailsScreen
584 chartURL = baseChartURL+"&t="+duration+"&s="+symbol;
585 logRequest(chartURL);
593 anchors {verticalCenter: parent.verticalCenter;verticalCenterOffset: 80; horizontalCenter: parent.horizontalCenter}
598 anchors.horizontalCenter: parent.horizontalCenter
601 anchors { verticalCenter: parent.verticalCenter}
602 width: 50; height: 32
603 onClicked: loadChart("1d");
608 anchors { verticalCenter: parent.verticalCenter}
609 width: 50; height: 32
610 onClicked: loadChart("5d");
615 anchors { verticalCenter: parent.verticalCenter}
616 width: 50; height: 32
617 onClicked: loadChart("3m");
622 anchors { verticalCenter: parent.verticalCenter}
623 width: 50; height: 32
624 onClicked: loadChart("6m");
631 anchors.horizontalCenter: parent.horizontalCenter
634 anchors { verticalCenter: parent.verticalCenter}
635 width: 50; height: 32
636 onClicked: loadChart("1y");
641 anchors { verticalCenter: parent.verticalCenter}
642 width: 50; height: 32
643 onClicked: loadChart("2y");
648 anchors { verticalCenter: parent.verticalCenter}
649 width: 50; height: 32
650 onClicked: loadChart("5y");
655 anchors { verticalCenter: parent.verticalCenter}
656 width: 50; height: 32
657 onClicked: loadChart("my");