Release 0.3-1 (Including all changes)
[marketstoday] / src / qml / MarketsTodayApp.qml
1 /*
2 @version: 0.2
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: screen
17
18     signal showConfigInNewWindow
19     signal showStockDetails(string strSymbol)
20     signal quoteRefreshStarted
21     signal quoteRefreshCompleted
22     signal checkNetworkStatus
23
24     property int itemHeight: 50
25     property int titleBarHeight: 60
26     property int toolBarHeight: 40
27     property int componentWidth: screen.width
28     property int autoUpdateInterval: 300000
29     property bool updateWeekDaysOnly: false
30     property bool updateOnSavedNetworksOnly: false
31     property string rssURL: "http://finance.yahoo.com/rss/topstories"
32     property string lastUpdatedTimeStamp
33     property bool isDesktopWidget
34     //property string selectedSymbol:"YHOO"
35     property string selectedSymbol:sharedContext.getStockSymbol()
36
37     function reloadData(){
38         CoreLib.reloadQuotes();
39         CoreLib.reloadNews();
40     }
41
42     function initialize(){
43         var componentToDisplay = sharedContext.getComponentToDisplay();
44         if (componentToDisplay === "StockQuoteDetails"){
45             uiLoader.sourceComponent = stockDetailsComponent;
46             titleBar.buttonType = "Close";
47             titleBar.displayMenu = false;
48             toolBar.displayIcons = false;
49         }
50         else{
51             CoreLib.initialize();
52             uiLoader.sourceComponent = stockQuotesUIComponent;
53         }
54     }
55
56     Component.onCompleted: {
57         initialize();
58     }
59
60     Timer {
61         id: autoUpdateTimer
62         interval: autoUpdateInterval
63         //running: (autoUpdateInterval == 0? false:true)
64         repeat: true
65         onTriggered: {
66             if (!updateWeekDaysOnly){
67                 logUtility.logMessage("Allowed to update all days of the week");
68                 reloadData();
69                 //checkNetworkStatus();
70             }
71             else if (Common.isTodayAWeekDay()){
72                 logUtility.logMessage("Today is a weekday");
73                 reloadData();
74                 //checkNetworkStatus();
75             }
76             else{
77                 logUtility.logMessage("Update not triggered: Today is not a weekday");
78             }
79         }
80     }
81
82     ListModel{
83         id: stockQuoteDataModel
84     }
85
86     ListModel {
87         id: newsDataModel
88     }
89
90     Rectangle {
91         id: background
92         anchors.fill: parent;
93         color: "#343434"
94         clip: true
95
96         Component {
97             id: stockQuotesDelegate
98
99             Item {
100                 id: wrapper; width: componentWidth; height: itemHeight
101                 Item {
102                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: wrapper.height - 2; width: wrapper.width; y: 1
103                         Image{
104                             id: informationIcon
105                             width: 32
106                             height: 32
107                             z: 10
108                             anchors {right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter}
109                             visible: false
110                             source: "Library/images/information.png"
111                             MouseArea{
112                                 anchors.fill: parent;
113                                 onPressed: {
114                                     //console.log("Image clicked");
115                                     screen.selectedSymbol = symbol;
116                                     uiLoader.sourceComponent = stockDetailsComponent;
117                                     titleBar.buttonType = "Back";
118                                     titleBar.displayMenu = false;
119                                     toolBar.displayIcons = false;
120                                 }
121                             }
122                         }
123
124                         MouseArea {
125                             anchors.fill: parent
126                             onPressed:{
127                                 informationIcon.visible = true;
128                                 //console.log("Rectangle clicked");
129                             }
130                         }
131                     }
132
133                     Row {
134                         x: 30;y: 15;
135                         width: componentWidth - 60;
136                         spacing: 5
137
138                         Text { text: stockName; width: parent.width * 30/100; font.pixelSize: 18; font.bold: true; elide: Text.ElideRight; color: "white"; style: Text.Raised; styleColor: "black" }
139                         Text { text: lastTradedPrice; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
140                         Text { text: change !== ""? (change + " ("+changePercentage+")"):""; width: parent.width * 25/100;  font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideRight
141                                 color: if(change >= 0){"green";} else {"red";}
142                                     style: Text.Raised; styleColor: "black" }
143                         Text { text: volume; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
144                         Text { text: marketCap; width: parent.width * 15/100; font.pixelSize: 18; horizontalAlignment: Text.AlignLeft; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
145                     }
146                 }
147             }
148         }
149
150         Component {
151             id: newsDelegate
152
153             Item {
154                 id: newsWrapper; width: componentWidth; height: itemHeight
155                 Item {
156                     anchors.fill: parent
157                     Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: newsWrapper.height - 2; width: newsWrapper.width; y: 1 }
158                     Text {
159                         anchors.verticalCenter: parent.verticalCenter
160                         anchors.left: parent.left
161                         anchors.leftMargin: 10
162                         anchors.right: parent.right
163                         text: title; font.pixelSize: 18
164                         font.bold: false;
165                         verticalAlignment: Text.AlignVCenter
166                         horizontalAlignment: Text.AlignLeft
167                         elide: Text.ElideRight;
168                         color: "white";
169                         style: Text.Raised;
170                         styleColor: "black"
171                     }
172                     MouseArea{
173                         anchors.fill: parent
174                         onClicked: Qt.openUrlExternally(link);
175                     }
176                 }
177             }
178         }
179
180         Library.TitleBar {
181             id: titleBar;
182             width: parent.width; height: screen.titleBarHeight;
183             anchors.top: parent.top
184             title: "Markets Today";
185             buttonType: "Close";
186             z: 5  //required to keep Titlebar and Menu buttons on top of everything else
187
188             onCloseClicked: Qt.quit()
189
190             onTickersClicked: {
191                 uiLoader.sourceComponent = configTickersComponent;
192                 titleBar.buttonType = "Back";
193                 titleBar.displayMenu = false;
194                 toolBar.displayIcons = false;
195             }
196
197             onOptionsClicked: {
198                 uiLoader.sourceComponent = configParamsComponent;
199                 titleBar.buttonType = "Back";
200                 titleBar.displayMenu = false;
201                 toolBar.displayIcons = false;
202             }
203
204             onBackClicked: {
205                 uiLoader.sourceComponent = stockQuotesUIComponent;
206                 titleBar.buttonType = "Close";
207                 titleBar.displayMenu = false;
208                 toolBar.displayIcons = true;
209                 screen.initialize();
210             }
211         }
212
213         Loader {
214             id: uiLoader
215             width: parent.width
216             anchors.top: titleBar.bottom
217             anchors.bottom: toolBar.top            
218         }
219
220         Library.ToolBar {
221             id:toolBar
222             width: parent.width; height: screen.toolBarHeight
223             anchors.bottom: parent.bottom
224             opacity: 0.9
225             displayNavigation: false
226             onReloadButtonClicked: screen.reloadData();
227
228             onNewsButtonClicked: {
229                 uiLoader.sourceComponent = newsComponent;
230                 toolBar.displayIcons = true;
231                 toolBar.targetContentType = "Stocks";
232             }
233
234             onStocksButtonClicked: {
235                 uiLoader.sourceComponent = stockQuotesUIComponent;
236                 toolBar.displayIcons = true;
237                 toolBar.targetContentType = "News";
238             }
239
240
241             Connections {
242                 target: screen
243                 onQuoteRefreshStarted:{
244                     if (!toolBar.updatePending) toolBar.updatePending = true;
245                 }
246                 onQuoteRefreshCompleted:{
247                     toolBar.updatePending = false;
248                 }
249             }
250         }
251
252
253
254         Component {
255             id: stockQuotesUIComponent
256             Item {
257                 Rectangle{
258                     id: listViewWrapper
259                     width: parent.width
260                     anchors.top: parent.top
261                     anchors.bottom: footerText.top
262                     color: "#343434"
263
264                     ListView {
265                         id: stockQuotesView
266                         anchors.fill: parent
267                         flickDeceleration: 500
268                         model: stockQuoteDataModel
269                         delegate:  stockQuotesDelegate
270                         focus:true
271                         snapMode: ListView.SnapToItem
272                     }
273                 }
274
275                 Rectangle{
276                     id: footerText
277                     width: parent.width
278                     height: 25
279                     color: "#343434"
280                     anchors.bottom: parent.bottom
281                     Text {
282                         id: timeStamp
283                         anchors.fill: parent
284                         text: screen.lastUpdatedTimeStamp
285                         horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
286                         width: parent.width; font.pixelSize: 12; elide: Text.ElideRight;
287                         color: "#cccccc"
288                         style: Text.Raised; styleColor: "black"
289
290                         Connections {
291                             target: screen
292                             onQuoteRefreshCompleted:{
293                                 timeStamp.text = screen.lastUpdatedTimeStamp;
294                             }
295                         }
296                     }
297                 }
298             }
299         }
300
301         Component{
302             id: stockDetailsComponent
303             StockDetailsComponent {
304                 symbol: selectedSymbol
305                 onLogRequest: logUtility.logMessage(strMessage)
306             }
307         }
308
309         Component {
310             id: newsComponent
311             Item {
312                 Rectangle{
313                     width: parent.width
314                     anchors.top: parent.top
315                     anchors.bottom: parent.bottom
316                     color: "#343434"
317
318                     ListView {
319                         id: newsView
320                         anchors.fill: parent
321                         flickDeceleration: 500
322                         model: newsDataModel
323                         delegate:  newsDelegate
324                         focus:true
325                         snapMode: ListView.SnapToItem
326                     }
327                 }
328             }
329         }                
330
331         Component {
332             id: configTickersComponent
333
334             ConfigTickersComponent{
335                 itemHeight: screen.itemHeight
336                 componentWidth: screen.componentWidth
337                 onLogRequest: logUtility.logMessage(strMessage)
338             }
339         }
340
341         Component {
342             id: configParamsComponent
343             ConfigParametersComponent{
344                 onLogRequest: logUtility.logMessage(strMessage)
345             }
346         }       
347     }
348 }