c3327b14beadd89f7b4a5e013964f62a3d6ef155
[marketstoday] / src / qml / MarketsTodayWidget.qml
1 /*
2 @version: 0.4
3 @author: Sudheer K. <scifi1947 at gmail.com>
4 @license: GNU General Public License
5 */
6
7 import Qt 4.7
8
9 import "Library" as Library
10 import "Library/js/ISODate.js" as DateLib
11 import "Library/js/DBUtility.js" as DBUtility
12 import "Library/js/CSVUtility.js" as CSVUtility
13 import "Library/js/Common.js" as Common
14 import "Library/js/CoreLogic.js" as CoreLib
15
16 Item {
17     id: mainPage
18
19     signal showConfigInNewWindow
20     signal showStockDetails(string strSymbol)
21     signal quoteRefreshStarted
22     signal quoteRefreshCompleted(bool success, string strMessage)
23     signal newsReloadCompleted(bool success, string strMessage)
24     signal checkNetworkStatus
25
26     property int itemHeight: 50
27     property int titleBarHeight: 60
28     property int toolBarHeight: 40
29     property int componentWidth: mainPage.width
30     property int autoUpdateInterval: 300000
31     property bool updateWeekDaysOnly: false
32     property bool updateOnSavedNetworksOnly: false
33     property bool isDesktopWidget: true
34     property string rssURL: "http://finance.yahoo.com/rss/topfinstories"
35     property string lastUpdatedTimeStamp
36     property string selectedSymbol:""
37
38     function reloadData(){
39         CoreLib.reloadQuotes();
40         CoreLib.reloadNews();
41     }
42
43     function initialize(){
44         DBUtility.initialize();
45         CoreLib.initialize();
46     }
47
48     Component.onCompleted: {
49         initialize();
50     }
51
52     Timer {
53         id: autoUpdateTimer
54         interval: autoUpdateInterval
55         //running: (autoUpdateInterval == 0? false:true)
56         repeat: true
57         onTriggered: {
58             if (!updateWeekDaysOnly){
59                 logUtility.logMessage("Allowed to update all days of the week");
60                 mainPage.reloadData();
61                 //checkNetworkStatus();
62             }
63             else if (Common.isTodayAWeekDay()){
64                 logUtility.logMessage("Today is a weekday");
65                 mainPage.reloadData();
66                 //checkNetworkStatus();
67             }
68             else{
69                 logUtility.logMessage("Update not triggered: Today is not a weekday");
70             }
71         }
72     }
73
74     ListModel{
75         id: stockQuoteDataModel
76     }
77
78     ListModel {
79         id: newsDataModel
80     }
81
82     Rectangle {
83         id: background
84         anchors.fill: parent;
85         color: "#343434"
86         clip: true
87
88         Component.onCompleted: {
89             console.log("Rectangle Height = "+background.height);
90         }
91
92         Component {
93             id: stockQuotesDelegate
94
95             Item {
96                 id: wrapper; width: parent.width; height: itemHeight
97                 Item {
98                     anchors.fill: parent
99                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: wrapper.height - 2; width: wrapper.width; y: 1
100                         Image{
101                             id: informationIcon
102                             width: 32
103                             height: 32
104                             z: 10
105                             anchors {right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter}
106                             visible: false
107                             source: "Library/images/information.png"
108                             MouseArea{
109                                 anchors.fill: parent;
110                                 onPressed: {
111                                     logUtility.logMessage("Image clicked");
112                                     showStockDetails(symbol);
113                                 }
114                             }
115                         }
116
117                         MouseArea {
118                             anchors.fill: parent
119                             onPressed:{
120                                 informationIcon.visible = true;
121                                 //console.log("Rectangle clicked");
122                             }
123                         }
124                     }
125                     Row {
126                         y: 15;//x: 30;
127                         anchors {left: parent.left;leftMargin: 10;right: parent.right;rightMargin: 10}
128                         //width: componentWidth;
129                         height: parent.height
130                         spacing: 5
131
132                         Text { text: symbol; width: parent.width * 25/100; font.pixelSize: 18; font.bold: true; verticalAlignment:Text.AlignVCenter; elide: Text.ElideRight; color: "white"; style: Text.Raised; styleColor: "black" }
133                         Text { text: lastTradedPrice; width: parent.width * 25/100; font.pixelSize: 18; verticalAlignment:Text.AlignVCenter; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
134                         Column {
135                             y: -15;
136                             width: parent.width * 20/100; height: parent.height
137                             spacing: 2
138                             Text { text: change; font.pixelSize: 16; elide: Text.ElideRight
139                                 color: change >= 0 ? "#00ff00":"#ff0000";
140                                     style: Text.Raised; styleColor: "black" }
141                             Text { text: changePercentage; font.pixelSize: 16; elide: Text.ElideRight;
142                                 color: change >= 0 ? "#00ff00":"#ff0000";
143                                     style: Text.Raised; styleColor: "black" }
144                         }
145                         Text { text: volume; width: parent.width * 30/100; font.pixelSize: 18; verticalAlignment:Text.AlignVCenter; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
146                     }
147                 }
148             }
149         }
150
151         Component {
152             id: newsDelegate
153
154             Item {
155                 id: newsWrapper; width: componentWidth; height: itemHeight
156                 Item {
157                     anchors.fill: parent
158                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: newsWrapper.height - 2; width: newsWrapper.width; y: 1 }
159                     Text {
160                         anchors.verticalCenter: parent.verticalCenter
161                         anchors.left: parent.left
162                         anchors.leftMargin: 10
163                         anchors.right: parent.right
164                         text: title; font.pixelSize: 14
165                         font.bold: false;
166                         verticalAlignment: Text.AlignVCenter
167                         horizontalAlignment: Text.AlignLeft
168                         elide: Text.ElideRight;
169                         color: "white";
170                         style: Text.Raised;
171                         styleColor: "black"
172                     }
173                     MouseArea{
174                         anchors.fill: parent
175                         onClicked: Qt.openUrlExternally(link);
176                     }
177                 }
178             }
179         }
180
181         Library.TitleBar {
182             id: titleBar
183             width: parent.width; height: mainPage.titleBarHeight
184             anchors.top: parent.top
185             title: "Markets Today"
186             buttonType: ""
187             displayMenuIcon: false
188
189             onBackClicked: {
190                 uiLoader.sourceComponent = stockQuotesUIComponent;
191                 titleBar.buttonType = "";
192                 titleBar.displayMenu = false;
193                 toolBar.displayIcons = true;
194             }
195         }
196
197         Loader {
198             id: uiLoader
199             width: parent.width
200             anchors.top: titleBar.bottom
201             anchors.bottom: toolBar.top
202             sourceComponent: stockQuotesUIComponent
203         }
204
205         Library.ToolBar {
206             id:toolBar
207             width: parent.width; height: mainPage.toolBarHeight
208             anchors.bottom: parent.bottom
209             opacity: 0.9
210             displayNavigation: true
211             onReloadButtonClicked: mainPage.reloadData();
212             onNewsButtonClicked: {
213                 uiLoader.sourceComponent = newsComponent;
214                 toolBar.displayIcons = true;
215                 toolBar.targetContentType = "Stocks";
216             }
217
218             onStocksButtonClicked: {
219                 uiLoader.sourceComponent = stockQuotesUIComponent;
220                 toolBar.displayIcons = true;
221                 toolBar.targetContentType = "News";
222             }
223
224
225             Connections {
226                 target: mainPage
227                 onQuoteRefreshStarted:{
228                     if (!toolBar.updatePending) toolBar.updatePending = true;
229                 }
230                 onQuoteRefreshCompleted:{
231                     toolBar.updatePending = false;
232                 }
233             }
234         }
235
236         Component {
237             id: stockQuotesUIComponent
238             Item {
239                 Rectangle{
240                     id: pathViewWrapper
241                     width: parent.width
242                     anchors.top: parent.top
243                     anchors.bottom: footerText.top
244                     color: "#343434"
245
246                     PathView {
247                         id: stockQuotesView
248                         anchors.fill: parent
249                         flickDeceleration: 500
250                         //preferredHighlightBegin: 1/stockQuotesView.count
251                         //preferredHighlightEnd: 1/stockQuotesView.count
252                         //pathItemCount: count
253                         focus: true
254                         interactive: true
255                         model: stockQuoteDataModel
256                         delegate:  stockQuotesDelegate
257                         path: Path {
258                             startX: width / 2
259                             startY: itemHeight/2
260                             PathLine {
261                                 x: width / 2
262                                 y: stockQuotesView.count * itemHeight  + itemHeight/2
263                             }
264                         }
265                         Keys.onDownPressed: if (!moving && interactive) incrementCurrentIndex()
266                         Keys.onUpPressed: if (!moving && interactive) decrementCurrentIndex()
267
268                         Connections {
269                             target:  mainPage
270                             onQuoteRefreshCompleted:{
271                                 stockQuotesView.currentIndex = 0;
272                             }
273                         }
274
275                         Connections {
276                             target: toolBar
277                             onDownButtonClicked: {
278                                 if (!stockQuotesView.moving && stockQuotesView.interactive)
279                                     stockQuotesView.currentIndex = stockQuotesView.currentIndex + 1
280                             }
281                             onUpButtonClicked: {
282                                 if (!stockQuotesView.moving && stockQuotesView.interactive)
283                                     stockQuotesView.currentIndex = stockQuotesView.currentIndex - 1
284                             }
285                        }
286                     }
287                 }
288
289                 Rectangle {
290                     id: stockStatusMsgArea
291                     height: 100
292                     color: "#343434"
293                     anchors {left: parent.left; leftMargin: 15; right: parent.right; rightMargin: 15;
294                             verticalCenter: parent.verticalCenter}
295                     visible: false
296
297                     Text {
298                         id: stockStatusText
299                         anchors.fill: parent
300                         text: "Loading quotes.."
301                         horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter
302                         width: parent.width; font.pixelSize: 16; elide: Text.ElideNone;
303                         color: "#cccccc"
304                         wrapMode: Text.WrapAtWordBoundaryOrAnywhere
305                         style: Text.Raised; styleColor: "black"
306
307                         Connections {
308                             target: mainPage
309                             onQuoteRefreshCompleted: {
310                                 if (success){                                    
311                                     stockStatusMsgArea.visible = false;
312                                     pathViewWrapper.visible = true;
313                                 }
314                                 else{
315                                     stockStatusText.text = strMessage;
316                                     pathViewWrapper.visible = false;
317                                     stockStatusMsgArea.visible = true;
318                                 }
319                             }
320                         }
321                     }
322                 }
323
324                 Rectangle{
325                     id: footerText
326                     width: parent.width
327                     height: 25
328                     color: "#343434"
329                     anchors.bottom: parent.bottom
330                     Text {
331                         id: timeStamp
332                         anchors.fill: parent
333                         text: mainPage.lastUpdatedTimeStamp
334                         horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
335                         width: parent.width; font.pixelSize: 12; elide: Text.ElideRight;
336                         color: "#cccccc"
337                         style: Text.Raised; styleColor: "black"
338
339                         Connections {
340                             target: mainPage
341                             onQuoteRefreshCompleted:{
342                                 timeStamp.text = mainPage.lastUpdatedTimeStamp;
343                             }
344                         }
345                     }
346                 }
347             }
348         }
349
350         Component {
351             id: newsComponent
352             Item {
353                 Rectangle{
354                     id: newsViewArea
355                     width: parent.width
356                     anchors.top: parent.top
357                     anchors.bottom: parent.bottom
358                     color: "#343434"
359
360                     PathView {
361                         id: newsView
362                         anchors.fill: parent
363                         flickDeceleration: 500
364                         focus: true
365                         interactive: true
366                         model: newsDataModel
367                         delegate:  newsDelegate
368                         path: Path {
369                             startX: width / 2
370                             startY: itemHeight/2
371                             PathLine {
372                                 x: width / 2
373                                 y: newsView.count * itemHeight  + itemHeight/2
374                             }
375                         }
376                         Keys.onDownPressed: if (!moving && interactive) incrementCurrentIndex()
377                         Keys.onUpPressed: if (!moving && interactive) decrementCurrentIndex()
378
379                         Connections {
380                             target:  mainPage
381                             onQuoteRefreshCompleted:{
382                                 newsView.currentIndex = 0;
383                             }
384                         }
385
386                         Connections {
387                             target: toolBar
388                             onDownButtonClicked: {
389                                 if (!newsView.moving && newsView.interactive)
390                                     newsView.currentIndex = newsView.currentIndex + 1
391                             }
392                             onUpButtonClicked: {
393                                 if (!newsView.moving && newsView.interactive)
394                                     newsView.currentIndex = newsView.currentIndex - 1
395                             }
396                        }
397                     }
398                 }
399
400                 Rectangle {
401                     id: newsStatusMsgArea
402                     height: 100
403                     color: "#343434"
404                     anchors {left: parent.left; leftMargin: 15; right: parent.right; rightMargin: 15;
405                             verticalCenter: parent.verticalCenter}
406                     visible: false
407
408                     Text {
409                         id: newsStatusText
410                         anchors.fill: parent
411                         text: "Loading news.."
412                         horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter
413                         width: parent.width; font.pixelSize: 16; elide: Text.ElideNone;
414                         color: "#cccccc"
415                         wrapMode: Text.WrapAtWordBoundaryOrAnywhere
416                         style: Text.Raised; styleColor: "black"
417
418                         Connections {
419                             target: mainPage
420                             onNewsReloadCompleted: {
421                                 if (success){
422                                     newsStatusMsgArea.visible = false;
423                                     newsViewArea.visible = true;
424                                 }
425                                 else{
426                                     newsStatusText.text = strMessage;
427                                     newsViewArea.visible = false;
428                                     newsStatusMsgArea.visible = true;
429                                 }
430                             }
431                         }
432                     }
433                 }
434             }
435         }
436     }
437 }