Release 0.4-0
[marketstoday] / src / qml / MarketsTodayLegacyApp.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/Common.js" as Common
13 import "Library/js/CoreLogic.js" as CoreLib
14
15 Item {
16     id: mainPage
17
18     signal showConfigInNewWindow
19     signal showStockDetails(string strSymbol)
20     signal quoteRefreshStarted
21     signal quoteRefreshCompleted(bool success, string strMessage)
22     signal newsReloadCompleted(bool success, string strMessage)
23     signal checkNetworkStatus
24
25     property int itemHeight: 50
26     property int titleBarHeight: 60
27     property int toolBarHeight: 40
28     property int componentWidth: mainPage.width
29     property int autoUpdateInterval: 300000
30     property bool updateWeekDaysOnly: false
31     property bool updateOnSavedNetworksOnly: false
32     property bool isDesktopWidget: false
33     property string rssURL: "http://finance.yahoo.com/rss/topfinstories"
34     property string lastUpdatedTimeStamp
35     //property string selectedSymbol:"YHOO"
36     property string selectedSymbol:sharedContext.getStockSymbol()
37
38     function reloadData(){
39         CoreLib.reloadQuotes();
40         CoreLib.reloadNews();
41     }
42
43     function initialize(){        
44         var componentToDisplay = sharedContext.getComponentToDisplay();
45         if (componentToDisplay === "StockQuoteDetails"){
46             uiLoader.sourceComponent = stockDetailsComponent;
47             titleBar.buttonType = "Close";
48             titleBar.displayMenu = false;
49             toolBar.displayIcons = false;
50         }
51         else{
52             DBUtility.initialize();
53             uiLoader.sourceComponent = stockQuotesUIComponent;
54             CoreLib.initialize();            
55         }
56     }
57
58     Component.onCompleted: {
59         initialize();
60     }
61
62     Timer {
63         id: autoUpdateTimer
64         interval: autoUpdateInterval
65         //running: (autoUpdateInterval == 0? false:true)
66         repeat: true
67         onTriggered: {
68             if (!updateWeekDaysOnly){
69                 logUtility.logMessage("Allowed to update all days of the week");
70                 mainPage.reloadData();
71                 //checkNetworkStatus();
72             }
73             else if (Common.isTodayAWeekDay()){
74                 logUtility.logMessage("Today is a weekday");
75                 mainPage.reloadData();
76                 //checkNetworkStatus();
77             }
78             else{
79                 logUtility.logMessage("Update not triggered: Today is not a weekday");
80             }
81         }
82     }
83
84     ListModel{
85         id: stockQuoteDataModel
86     }
87
88     ListModel {
89         id: newsDataModel
90     }
91
92     Rectangle {
93         id: background
94         anchors.fill: parent;
95         color: "#343434"
96         clip: true
97
98         Component {
99             id: stockQuotesDelegate
100
101             Item {
102                 id: wrapper; width: mainPage.componentWidth; height: mainPage.itemHeight
103                 Item {
104                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: wrapper.height - 2; width: wrapper.width; y: 1
105                         MouseArea {
106                             anchors.fill: parent
107                             onDoubleClicked: {
108                                 mainPage.selectedSymbol = symbol;
109                                 uiLoader.sourceComponent = stockDetailsComponent;
110                                 titleBar.buttonType = "Back";
111                                 titleBar.displayMenu = false;
112                                 toolBar.displayIcons = false;
113                             }
114                         }
115                         /*
116                         Image{
117                             id: informationIcon
118                             width: 32
119                             height: 32
120                             z: 10
121                             anchors {right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter}
122                             visible: false
123                             source: "Library/images/information.png"
124                             MouseArea{
125                                 anchors.fill: parent;
126                                 onPressed: {
127                                     //console.log("Image clicked");
128                                     mainPage.selectedSymbol = symbol;
129                                     uiLoader.sourceComponent = stockDetailsComponent;
130                                     titleBar.buttonType = "Back";
131                                     titleBar.displayMenu = false;
132                                     toolBar.displayIcons = false;
133                                 }
134                             }
135                         }
136
137                         MouseArea {
138                             anchors.fill: parent
139                             onPressed:{
140                                 informationIcon.visible = true;
141                                 //console.log("Rectangle clicked");
142                             }
143                         }
144                         */
145                     }
146
147                     Row {
148                         x: 30;y: 15;
149                         width: mainPage.componentWidth - 60;
150                         spacing: 5
151
152                         Text { text: stockName; width: parent.width * 30/100; font.pixelSize: 18; font.bold: true; elide: Text.ElideRight; color: "white"; style: Text.Raised; styleColor: "black" }
153                         Text { text: lastTradedPrice; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
154                         Text { text: change !== ""? (change + " ("+changePercentage+")"):""; width: parent.width * 25/100;  font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideRight
155                                 color: if(change >= 0){"green";} else {"red";}
156                                     style: Text.Raised; styleColor: "black" }
157                         Text { text: volume; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
158                         Text { text: marketCap; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
159                     }
160                 }
161             }
162         }
163
164         Component {
165             id: newsDelegate
166
167             Item {
168                 id: newsWrapper; width: mainPage.componentWidth; height: mainPage.itemHeight
169                 Item {
170                     anchors.fill: parent
171                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: newsWrapper.height - 2; width: newsWrapper.width; y: 1 }
172                     Text {
173                         anchors.verticalCenter: parent.verticalCenter
174                         anchors.left: parent.left
175                         anchors.leftMargin: 10
176                         anchors.right: parent.right
177                         text: title; font.pixelSize: 18
178                         font.bold: false;
179                         verticalAlignment: Text.AlignVCenter
180                         horizontalAlignment: Text.AlignLeft
181                         elide: Text.ElideRight;
182                         color: "white";
183                         style: Text.Raised;
184                         styleColor: "black"
185                     }
186                     MouseArea{
187                         anchors.fill: parent
188                         onDoubleClicked: Qt.openUrlExternally(link);
189                     }
190                 }
191             }
192         }
193
194         Library.TitleBar {
195             id: titleBar;
196             width: parent.width; height: mainPage.titleBarHeight;
197             anchors.top: parent.top
198             title: "Markets Today";
199             buttonType: "Close";
200             z: 5  //required to keep Titlebar and Menu buttons on top of everything else
201
202             onCloseClicked: Qt.quit()
203
204             onTickersClicked: {
205                 uiLoader.sourceComponent = configTickersComponent;
206                 titleBar.buttonType = "Back";
207                 titleBar.displayMenu = false;
208                 toolBar.displayIcons = false;
209             }
210
211             onOptionsClicked: {
212                 uiLoader.sourceComponent = configParamsComponent;
213                 titleBar.buttonType = "Back";
214                 titleBar.displayMenu = false;
215                 toolBar.displayIcons = false;
216             }
217
218             onBackClicked: {
219                 uiLoader.sourceComponent = stockQuotesUIComponent;
220                 titleBar.buttonType = "Close";
221                 titleBar.displayMenu = false;
222                 toolBar.displayIcons = true;
223                 mainPage.initialize();
224             }
225         }
226
227         Loader {
228             id: uiLoader
229             width: parent.width
230             anchors.top: titleBar.bottom
231             anchors.bottom: toolBar.top            
232         }
233
234         Library.ToolBar {
235             id:toolBar
236             width: parent.width; height: mainPage.toolBarHeight
237             anchors.bottom: parent.bottom
238             opacity: 0.9
239             displayNavigation: false
240             onReloadButtonClicked: mainPage.reloadData();
241
242             onNewsButtonClicked: {
243                 uiLoader.sourceComponent = newsComponent;
244                 toolBar.displayIcons = true;
245                 toolBar.targetContentType = "Stocks";
246             }
247
248             onStocksButtonClicked: {
249                 uiLoader.sourceComponent = stockQuotesUIComponent;
250                 toolBar.displayIcons = true;
251                 toolBar.targetContentType = "News";
252             }
253
254
255             Connections {
256                 target: mainPage
257                 onQuoteRefreshStarted:{
258                     if (!toolBar.updatePending) toolBar.updatePending = true;
259                 }
260                 onQuoteRefreshCompleted:{
261                     toolBar.updatePending = false;
262                 }
263             }
264         }
265
266
267
268         Component {
269             id: stockQuotesUIComponent
270             Item {
271                 Rectangle{
272                     id: listViewWrapper
273                     width: parent.width
274                     anchors.top: parent.top
275                     anchors.bottom: footerTextArea.top
276                     color: "#343434"
277
278                     ListView {
279                         id: stockQuotesView
280                         anchors.fill: parent
281                         flickDeceleration: 500
282                         model: stockQuoteDataModel
283                         delegate:  stockQuotesDelegate
284                         focus:true
285                         snapMode: ListView.SnapToItem
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                                     listViewWrapper.visible = true;
313                                 }
314                                 else{
315                                     stockStatusText.text = strMessage;
316                                     listViewWrapper.visible = false;
317                                     stockStatusMsgArea.visible = true;
318                                 }
319                             }
320                         }
321                     }
322                 }
323
324                 Rectangle{
325                     id: footerTextArea
326                     width: parent.width
327                     height: 25
328                     color: "#343434"
329                     anchors.bottom: parent.bottom
330                     Text {
331                         id: footerMessage
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
340                     Timer {
341                         id: footerMessageTimer
342                         interval: 10000
343                         repeat: false
344                         onTriggered: {
345                             footerMessage.text = mainPage.lastUpdatedTimeStamp;
346                         }
347                     }
348
349                     Connections {
350                         target: mainPage
351                         onQuoteRefreshCompleted:{
352                             if (success){
353                                 footerMessage.text = "Double-tap on a row to display more details.";
354                                 footerMessageTimer.start();
355                             }
356                             else{
357                                 footerMessage.text = mainPage.lastUpdatedTimeStamp;
358                             }
359                         }
360                     }
361                 }
362             }
363         }
364
365         Component{
366             id: stockDetailsComponent
367             StockDetailsComponent {
368                 symbol: selectedSymbol
369                 onLogRequest: logUtility.logMessage(strMessage)
370             }
371         }
372
373         Component {
374             id: newsComponent
375             Item {
376                 Rectangle{
377                     id: newsViewArea
378                     width: parent.width
379                     anchors.top: parent.top
380                     anchors.bottom: parent.bottom
381                     color: "#343434"
382
383                     ListView {
384                         id: newsView
385                         anchors.fill: parent
386                         flickDeceleration: 500
387                         model: newsDataModel
388                         delegate:  newsDelegate
389                         focus:true
390                         snapMode: ListView.SnapToItem
391                     }
392                 }
393
394                 Rectangle {
395                     id: newsStatusMsgArea
396                     height: 100
397                     color: "#343434"
398                     anchors {left: parent.left; leftMargin: 15; right: parent.right; rightMargin: 15;
399                             verticalCenter: parent.verticalCenter}
400                     visible: false
401
402                     Text {
403                         id: newsStatusText
404                         anchors.fill: parent
405                         text: "Loading news.."
406                         horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter
407                         width: parent.width; font.pixelSize: 16; elide: Text.ElideNone;
408                         color: "#cccccc"
409                         wrapMode: Text.WrapAtWordBoundaryOrAnywhere
410                         style: Text.Raised; styleColor: "black"
411
412                         Connections {
413                             target: mainPage
414                             onNewsReloadCompleted: {
415                                 if (success){
416                                     newsStatusMsgArea.visible = false;
417                                     newsViewArea.visible = true;
418                                 }
419                                 else{
420                                     newsStatusText.text = strMessage;
421                                     newsViewArea.visible = false;
422                                     newsStatusMsgArea.visible = true;
423                                 }
424                             }
425                         }
426                     }
427                 }
428             }
429         }                
430
431         Component {
432             id: configTickersComponent
433
434             ConfigTickersComponent{
435                 itemHeight: mainPage.itemHeight
436                 componentWidth: mainPage.componentWidth
437                 onLogRequest: logUtility.logMessage(strMessage)
438             }
439         }
440
441         Component {
442             id: configParamsComponent
443             ConfigParametersComponent{
444                 onLogRequest: logUtility.logMessage(strMessage)
445             }
446         }       
447     }
448 }