3 @author: Sudheer K. <scifi1947 at gmail.com>
4 @license: GNU General Public License
8 import "Library" as Library
9 import "Library/js/CSVUtility.js" as CSVUtility
16 id: stockDetailsScreen
17 property int componentWidth: width
18 property int itemHeight: 50
19 property string symbol: "YHOO"
20 property string stockName: ""
21 property string lastTradedPrice: ""
22 property string lastTradedDateTime: ""
23 property string change: ""
24 property string changePercentage: ""
25 property string daysRange: ""
26 property string yearRange: ""
27 property string marketVolume: ""
28 property string prevClose: ""
29 property string marketCap: ""
30 property string baseChartURL: "http://chart.finance.yahoo.com/z?q=&l=&z=m&p=s&a=v&p=s&lang=en-US®ion=US"
31 property string chartURL: ""
32 property string rssURL: ""
33 property string orientation: "Portrait"
35 property int currentScreenIndex: 1
37 signal logRequest(string strMessage)
38 signal loadChart(string duration)
45 Library.CustomGestureArea {
47 onSwipeLeft: detailsRect.switchScreen()
48 onSwipeRight: detailsRect.switchScreen()
51 Component.onCompleted: {
55 chartURL = baseChartURL+"&t=1d&s="+symbol;
59 function switchScreen(){
60 switch (currentScreenIndex){
62 stockDetailsLoader.sourceComponent = (stockDetailsScreen.width > stockDetailsScreen.height)? stockChartComponentLandscape : stockChartComponentPortrait;
63 currentScreenIndex = currentScreenIndex + 1;
66 stockDetailsLoader.sourceComponent = stockDetailsComponent;
67 currentScreenIndex = currentScreenIndex - 1;
72 logRequest("currentScreenIndex = "+currentScreenIndex);
75 function loadDetails(){
76 var queryURL = 'http://download.finance.yahoo.com/d/quotes.csv?s='+symbol+'&f=snl1d1t1c1p2mwvpj1&e=.csv';
77 //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';
78 logRequest("Loading stock details from "+queryURL);
79 var response = new XMLHttpRequest();
80 response.onreadystatechange = function() {
81 if (response.readyState === XMLHttpRequest.DONE) {
82 refreshDetails(response.responseText);
86 response.open("GET", queryURL);
91 rssURL = "http://feeds.finance.yahoo.com/rss/2.0/headline?region=US&lang=en-US&s="+symbol;
92 logRequest("Loading news from "+rssURL);
93 var response = new XMLHttpRequest();
94 response.onreadystatechange = function() {
95 if (response.readyState === XMLHttpRequest.DONE) {
96 refreshNewsModel(response.responseXML);
100 response.open("GET", rssURL);
104 function refreshDetails(responseText){
106 logUtility("No responseText for quote "+symbol);
110 var quoteDetails = CSVUtility.csvToArray(responseText.trim());
111 if (quoteDetails && quoteDetails.length > 0){
112 //We are only expecting one quote row per symbol.
114 var lastTradedDate = "", lastTradedTime ="";
115 stockName = quoteDetails[0][1];
116 lastTradedPrice = quoteDetails[0][2];
117 lastTradedDate = quoteDetails[0][3];
118 lastTradedTime = quoteDetails[0][4];
119 change = quoteDetails[0][5];
120 changePercentage = quoteDetails[0][6];
121 daysRange = quoteDetails[0][7];
122 yearRange = quoteDetails[0][8];
123 marketVolume = quoteDetails[0][9];
124 prevClose = quoteDetails[0][10];
125 marketCap = quoteDetails[0][11];
126 if (lastTradedDate !== "") lastTradedDateTime = lastTradedDate + " " + lastTradedTime;
129 logRequest("No results for stock quote details");
133 function refreshNewsModel(responseXML){
134 if (!(responseXML && stockNewsDataModel)) return;
136 var xmlDoc = responseXML.documentElement;
137 var channel = xmlDoc.firstChild;
139 //Not the best code I ever wrote, but got no choice
140 //Refer to Memory leak issue with XMLListModel --> http://bugreports.qt.nokia.com/browse/QTBUG-15191
143 var itemNodes = channel.childNodes;
146 logRequest("Clearing News Model");
147 stockNewsDataModel.clear();
150 for (i = 0; i < itemNodes.length; i++) {
152 if (itemNodes[i].nodeName === 'item'){
153 var newsElements = itemNodes[i].childNodes;
155 var newsTitle,newsLink
156 for (j = 0; j < newsElements.length; j++){
158 switch (newsElements[j].nodeName){
160 newsTitle = newsElements[j].childNodes[0].nodeValue;
163 newsLink = newsElements[j].childNodes[0].nodeValue;
168 stockNewsDataModel.append({"title":newsTitle,"link":newsLink});
176 id: stockNewsDataModel
180 id: stockNewsDelegate
183 id: newsWrapper; width: stockDetailsLoader.width; height: itemHeight
186 Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: newsWrapper.height - 2; width: newsWrapper.width; y: 1 }
188 anchors {verticalCenter: parent.verticalCenter;left: parent.left;leftMargin: 10;right: parent.right}
189 text: title; font.pixelSize: 14
191 verticalAlignment: Text.AlignVCenter
192 horizontalAlignment: Text.AlignLeft
193 elide: Text.ElideRight;
198 Library.CustomGestureArea {
201 logRequest("Opening news article: "+link);
202 Qt.openUrlExternally(link);
204 onSwipeLeft: detailsRect.switchScreen()
205 onSwipeRight: detailsRect.switchScreen()
212 id: stockDetailsComponent
219 anchors.top: parent.top
221 anchors.horizontalCenter: parent.horizontalCenter
223 horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter
224 font.pixelSize: 18; font.bold: true; elide: Text.ElideMiddle; color: "#B8B8B8"; style: Text.Raised; styleColor: "black"
225 text: (stockName != "")? (stockName +" ("+symbol+")"):symbol
230 id: stockDetailsSection
232 border.color: "#BFBFBF"
234 anchors {top: stockNameLabel.bottom;left: parent.left;right: parent.right}
239 id: stockDetailsColumn
240 anchors {top: parent.top; left: parent.left; leftMargin: 10}
244 label1: "Last Traded"
245 value1: lastTradedPrice
246 cell1Width: stockDetailsColumn.width/2
248 label2: "Day's Range"
250 cell2Width: stockDetailsColumn.width/2
254 label1: "Last Trade Time"
255 value1: lastTradedDateTime
256 cell1Width: stockDetailsColumn.width/2
260 cell2Width: stockDetailsColumn.width/2
265 value1: ((change != "" && changePercentage != "")? change + " ("+changePercentage+")":"")
266 cell1Width: stockDetailsColumn.width/2
270 cell2Width: stockDetailsColumn.width/2
274 label1: "Prev. Close"
276 cell1Width: stockDetailsColumn.width/2
280 cell2Width: stockDetailsColumn.width/2
287 border.color: "#BFBFBF"
290 anchors {top: stockDetailsSection.bottom;topMargin: 5;
291 bottom: parent.bottom;
295 flickDeceleration: 500
297 model: stockNewsDataModel
298 delegate: stockNewsDelegate
300 snapMode: ListView.SnapToItem
308 id: stockDetailsLoader
309 anchors{top: parent.top; bottom: parent.bottom; bottomMargin: 20;
310 left: parent.left; leftMargin: 10
311 right: parent.right; rightMargin: 10}
312 sourceComponent: stockDetailsComponent
315 target: stockDetailsScreen
316 onOrientationChanged: {
317 logRequest("Orientation Changed");
318 logRequest("New orientation is "+stockDetailsScreen.orientation);
319 logRequest("Margins for StockDetailsLoader are "+stockDetailsLoader.anchors.leftMargin+", "+stockDetailsLoader.anchors.rightMargin);
321 if (currentScreenIndex === 2){
322 if (stockDetailsScreen.orientation == "Landscape")
323 stockDetailsLoader.sourceComponent = stockChartComponentLandscape;
325 stockDetailsLoader.sourceComponent = stockChartComponentPortrait;
337 anchors.top: stockDetailsLoader.bottom
341 text: "Swipe horizontally to switch between details and charts."
342 horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
343 width: parent.width; font.pixelSize: 12; elide: Text.ElideRight;
345 style: Text.Raised; styleColor: "black"
349 id: footerMessageTimer
353 footerMessage.text = "";
357 Component.onCompleted: {
358 footerMessageTimer.start();
363 id: stockChartComponentLandscape
366 id: chartAreaWrapperLand
372 border.color: "#BFBFBF"
375 anchors { top: parent.top;topMargin: 40;
376 bottom: parent.bottom; bottomMargin: 20;
377 left: parent.left; right: parent.right}
380 Library.Loading { anchors.centerIn: parent; visible: chartImg.status == Image.Loading}
384 anchors {left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter}
386 sourceSize.width: 512
387 sourceSize.height: 288
389 fillMode: Image.PreserveAspectFit
393 logRequest("Image is ready");
396 logRequest("Image is loading");
399 logRequest("Image loading failed");
402 logRequest("No image specified");
409 target: stockDetailsScreen
411 chartURL = baseChartURL+"&t="+duration+"&s="+symbol;
412 logRequest(chartURL);
420 anchors {top: parent.top; topMargin: 40; bottom: parent.bottom;
421 right: chartAreaLand.right;rightMargin: 10}
426 anchors.horizontalCenter: parent.horizontalCenter
429 anchors { verticalCenter: parent.verticalCenter}
430 width: 50; height: 32
431 onClicked: loadChart("1d");
436 anchors { verticalCenter: parent.verticalCenter}
437 width: 50; height: 32
438 onClicked: loadChart("5d");
445 anchors.horizontalCenter: parent.horizontalCenter
448 anchors { verticalCenter: parent.verticalCenter}
449 width: 50; height: 32
450 onClicked: loadChart("3m");
455 anchors { verticalCenter: parent.verticalCenter}
456 width: 50; height: 32
457 onClicked: loadChart("6m");
463 anchors.horizontalCenter: parent.horizontalCenter
466 anchors { verticalCenter: parent.verticalCenter}
467 width: 50; height: 32
468 onClicked: loadChart("1y");
473 anchors { verticalCenter: parent.verticalCenter}
474 width: 50; height: 32
475 onClicked: loadChart("2y");
481 anchors.horizontalCenter: parent.horizontalCenter
484 anchors { verticalCenter: parent.verticalCenter}
485 width: 50; height: 32
486 onClicked: loadChart("5y");
491 anchors { verticalCenter: parent.verticalCenter}
492 width: 50; height: 32
493 onClicked: loadChart("my");
502 id: stockChartComponentPortrait
505 id: chartAreaWrapperPort
511 border.color: "#BFBFBF"
514 anchors { top: parent.top;topMargin: 40;
515 bottom: parent.bottom; bottomMargin: 20;
516 left: parent.left; right: parent.right}
519 Library.Loading { anchors.centerIn: parent; visible: chartImgPort.status == Image.Loading}
523 //anchors {left: parent.left; leftMargin: 10; horizontalCenter: parent.horizontalCenter}
524 anchors {horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 40}
526 sourceSize.width: 512
527 sourceSize.height: 288
529 fillMode: Image.PreserveAspectFit
530 width: parent.width - 20
534 logRequest("Image is ready");
537 logRequest("Image is loading");
540 logRequest("Image loading failed");
543 logRequest("No image specified");
550 target: stockDetailsScreen
552 chartURL = baseChartURL+"&t="+duration+"&s="+symbol;
553 logRequest(chartURL);
561 anchors {verticalCenter: parent.verticalCenter;verticalCenterOffset: 80; horizontalCenter: parent.horizontalCenter}
566 anchors.horizontalCenter: parent.horizontalCenter
569 anchors { verticalCenter: parent.verticalCenter}
570 width: 50; height: 32
571 onClicked: loadChart("1d");
576 anchors { verticalCenter: parent.verticalCenter}
577 width: 50; height: 32
578 onClicked: loadChart("5d");
583 anchors { verticalCenter: parent.verticalCenter}
584 width: 50; height: 32
585 onClicked: loadChart("3m");
590 anchors { verticalCenter: parent.verticalCenter}
591 width: 50; height: 32
592 onClicked: loadChart("6m");
599 anchors.horizontalCenter: parent.horizontalCenter
602 anchors { verticalCenter: parent.verticalCenter}
603 width: 50; height: 32
604 onClicked: loadChart("1y");
609 anchors { verticalCenter: parent.verticalCenter}
610 width: 50; height: 32
611 onClicked: loadChart("2y");
616 anchors { verticalCenter: parent.verticalCenter}
617 width: 50; height: 32
618 onClicked: loadChart("5y");
623 anchors { verticalCenter: parent.verticalCenter}
624 width: 50; height: 32
625 onClicked: loadChart("my");