From: Charles Yin Date: Fri, 13 Jul 2012 06:28:44 +0000 (+1000) Subject: Rewrite stockchart demo X-Git-Tag: upstream/5.2.1~1418 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=288e11388d2c5f393c177b4ecb2145919cbb511a;p=platform%2Fupstream%2Fqtdeclarative.git Rewrite stockchart demo Change-Id: Ie931d116f3ac16245d56b8c1539e5c4f2dc490f0 Reviewed-by: Yunqiao Yin --- diff --git a/examples/demos/stockchart/README b/examples/demos/stockchart/README deleted file mode 100644 index 2652866..0000000 --- a/examples/demos/stockchart/README +++ /dev/null @@ -1,5 +0,0 @@ -To run: - - make install - QML_IMPORT_PATH=$PWD qmlscene stock.qml - diff --git a/examples/demos/stockchart/com/nokia/StockChartExample/qmldir b/examples/demos/stockchart/com/nokia/StockChartExample/qmldir deleted file mode 100644 index 4c60e55..0000000 --- a/examples/demos/stockchart/com/nokia/StockChartExample/qmldir +++ /dev/null @@ -1 +0,0 @@ -plugin qmlstockchartexampleplugin diff --git a/examples/demos/stockchart/contents/ToolBar.qml b/examples/demos/stockchart/content/Button.qml similarity index 79% rename from examples/demos/stockchart/contents/ToolBar.qml rename to examples/demos/stockchart/content/Button.qml index 7ae7391..325bd8f 100644 --- a/examples/demos/stockchart/contents/ToolBar.qml +++ b/examples/demos/stockchart/content/Button.qml @@ -40,30 +40,20 @@ import QtQuick 2.0 -Item { - id: toolbar - - property variant labels - signal buttonClicked(int index) - - BorderImage { - source: "images/titlebar.sci" - width: parent.width - height: parent.height + 14 - y: -7 +Rectangle { + id:button + property bool buttonEnabled:true + radius:5 + width:25 + height:25 + color:buttonEnabled ? "steelblue" : "gray" + MouseArea { + anchors.fill:parent + onClicked: { + if (buttonEnabled) + buttonEnabled = false; + else + buttonEnabled = true; } - - Row { - y: 3 - anchors.horizontalCenter: parent.horizontalCenter - Repeater { - model: toolbar.labels - delegate: - Button { - text: modelData - onClicked: toolbar.buttonClicked(model.index) - } - } - } - + } } diff --git a/examples/demos/stockchart/contents/ScrollBar.qml b/examples/demos/stockchart/content/DatePicker.qml similarity index 51% rename from examples/demos/stockchart/contents/ScrollBar.qml rename to examples/demos/stockchart/content/DatePicker.qml index 98b8efe..a85d4f2 100644 --- a/examples/demos/stockchart/contents/ScrollBar.qml +++ b/examples/demos/stockchart/content/DatePicker.qml @@ -3,7 +3,7 @@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** -** This file is part of the Qt Mobility Components. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -40,35 +40,83 @@ import QtQuick 2.0 -Item { - id: scrollBar - // The properties that define the scrollbar's state. - // position and pageSize are in the range 0.0 - 1.0. They are relative to the - // height of the page, i.e. a pageSize of 0.5 means that you can see 50% - // of the height of the view. - // orientation can be either 'Vertical' or 'Horizontal' - property real position - property real pageSize - property string orientation : "Vertical" - property alias bgColor: background.color - property alias fgColor: thumb.color +Rectangle { + id:root + color:"transparent" + width:300 + height:45 + property var _monthNames : [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN","JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; + property var date:new Date() + + onDateChanged: { + month.text = root._monthNames[root.date.getMonth()] + day.text = date.getDate(); + year.text = date.getFullYear(); + } + Row { + spacing:20 + anchors.fill:parent + + Rectangle { + height:root.height + width:root.width/3 - 20 + color:"#272822" + radius:5 + + TextInput { + id:month + anchors.centerIn:parent + color:"#ecc089" + font.pointSize:25 + font.bold:true + text:root._monthNames[root.date.getMonth()] + onAccepted : { + for (var i = 0; i < 12; i++) { + if (text === root._monthNames[i]) { + root.date.setMonth(i); + root.date = root.date; + return; + } + } + root.date = root.date; + } + } + } - // A light, semi-transparent background Rectangle { - id: background - radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1) - color: "white"; opacity: 0.3 - anchors.fill: parent + height:root.height + width:root.width/3 - 20 + color:"#272822" + radius:5 + + TextInput { + id:day + anchors.centerIn:parent + color:"#ecc089" + font.pointSize:25 + font.bold:true + text:root.date.getDate() + validator:IntValidator {bottom:1; top:31} + onAccepted: { root.date.setDate(text); root.date = root.date;} + } } - // Size the bar to the required size, depending upon the orientation. + Rectangle { - id: thumb - opacity: 0.7 - color: "black" - radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1) - x: orientation == 'Vertical' ? 1 : (scrollBar.position * (scrollBar.width-2) + 1) - y: orientation == 'Vertical' ? (scrollBar.position * (scrollBar.height-2) + 1) : 1 - width: orientation == 'Vertical' ? (parent.width-2) : (scrollBar.pageSize * (scrollBar.width-2)) - height: orientation == 'Vertical' ? (scrollBar.pageSize * (scrollBar.height-2)) : (parent.height-2) + height:root.height + width:root.width/3 - 20 + color:"#272822" + radius:5 + + TextInput { + id:year + anchors.centerIn:parent + color:"#ecc089" + font.pointSize:25 + font.bold:true + text:root.date.getFullYear() + validator:IntValidator {bottom:1995; top:(new Date()).getFullYear()} + onAccepted:{ root.date.setFullYear(text); root.date = root.date;} + } } + } } diff --git a/examples/demos/stockchart/content/StockChart.qml b/examples/demos/stockchart/content/StockChart.qml new file mode 100644 index 0000000..9dc1ea3 --- /dev/null +++ b/examples/demos/stockchart/content/StockChart.qml @@ -0,0 +1,324 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +Rectangle { + id:chart + width:320 + height:320 + color:"transparent" + property var _months : [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] + property var stockModel:null + property var startDate + property var endDate + property var settings + + function update() { + if (settings.chartType === "year") + chart.startDate = new Date(chart.endDate.getFullYear() - 1, chart.endDate.getMonth(), chart.endDate.getDate()); + else if (settings.chartType === "month") + chart.startDate = new Date(chart.endDate.getFullYear() , chart.endDate.getMonth() -1, chart.endDate.getDate()) + else if (settings.chartType === "week") + chart.startDate = new Date(chart.endDate.getFullYear() , chart.endDate.getMonth(), chart.endDate.getDate() - 7) + else + chart.startDate = new Date(1995, 3, 25) + + canvas.requestPaint(); + } + + + Text { + id:fromDate + color:"#6a5b44" + width:50 + font.pointSize: 10 + wrapMode: Text.WordWrap + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top:parent.top + text:_months[startDate.getMonth()] + "\n" + startDate.getFullYear() + } + + Text { + id:toDate + color:"#6a5b44" + font.pointSize: 10 + width:50 + wrapMode: Text.WordWrap + anchors.right: parent.right + anchors.leftMargin: 20 + anchors.top:parent.top + text:_months[endDate.getMonth()] + "\n" + endDate.getFullYear() + } + + Canvas { + id:canvas + anchors.top : toDate.bottom + width:parent.width + anchors.bottom: parent.bottom + + renderTarget: Canvas.FramebufferObject + property int frames:first + property int mouseX:0; + property int mouseY:0; + property int mousePressedX:0; + property int mousePressedY:0; + property int movedY:0 + property real scaleX:1.0; + property real scaleY:1.0; + property int first:0; + property int last:0; + +// MouseArea { +// anchors.fill: parent + +// onPositionChanged: { +// if (mouse.modifiers & Qt.ControlModifier) { +// if (canvas.mouseX == 0 && canvas.mouseY == 0) { +// canvas.mouseX = mouse.x; +// canvas.mouseY = mouse.y; +// } +// } else{ +// var w = (view.width/view.count)*canvas.scaleX; + +// //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2); + +// var movedX = Math.round((canvas.mousePressedX - mouse.x)/w); +// if (movedX != 0 || canvas.movedY != 0) { +// if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) { +// canvas.first += movedX; +// canvas.last += movedX; +// } +// canvas.requestPaint(); +// } +// } +// } + +// onPressed: { +// canvas.mousePressedX = mouse.x; +// canvas.mousePressedY = mouse.y; +// } + +// onReleased : { +// if (mouse.modifiers & Qt.ControlModifier) { +// var sx = mouse.x - canvas.mouseX; +// var sy = canvas.mouseY - mouse.y; + +// if (Math.abs(sx) < 50) sx = 0; +// if (Math.abs(sy) < 50) sy = 0; + +// if (sx > 0) +// canvas.scaleX *= sx/100 +1; +// else +// canvas.scaleX *= 1/(-sx/100 + 1); + +// if (sy > 0) +// canvas.scaleY *= sy/100 +1; +// else +// canvas.scaleY *= 1/(-sy/100 + 1); + +// if (canvas.scaleX < 1) +// canvas.scaleX = 1; + +// //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY); + +// canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); +// canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); + +// canvas.mouseX = 0; +// canvas.mouseY = 0; +// canvas.mousePressedX = 0; +// canvas.mousePressedY = 0; +// canvas.requestPaint(); +// } +// } +// } + + function drawBackground(ctx) { + ctx.save(); + ctx.fillStyle = "#272822" + ctx.fillRect(0, 0, canvas.width, canvas.height) + ctx.strokeStyle = "#423a2f" + ctx.beginPath(); + for (var i = 0; i < 10; i++) { + ctx.moveTo(0, i * (canvas.height/10.0)); + ctx.lineTo(canvas.width, i * (canvas.height/10.0)); + } + + for (i = 0; i < 12; i++) { + ctx.moveTo(i * (canvas.width/12.0), 0); + ctx.lineTo(i * (canvas.width/12.0), canvas.height); + } + ctx.stroke(); + + ctx.strokeStyle = "#5c7a37" + ctx.beginPath(); + ctx.moveTo(8 * (canvas.width/12.0), 0); + ctx.lineTo(8 * (canvas.width/12.0), canvas.height); + ctx.stroke(); + + ctx.restore(); + } + + function drawPrice(ctx, from, to, color, price, points, highest) + { + ctx.save(); + ctx.globalAlpha = 0.7; + ctx.strokeStyle = color; + ctx.lineWidth = 1; + ctx.beginPath(); + + var w = canvas.width/points.length; + var end = points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var y = points[i][price]; + y = canvas.height * y/highest; + if (i == 0) { + ctx.moveTo(x+w/2, y); + } else { + ctx.lineTo(x+w/2, y); + } + } + ctx.stroke(); + ctx.restore(); + } + + function drawKLine(ctx, from, to, points, highest) + { + ctx.save(); + ctx.globalAlpha = 0.4; + ctx.lineWidth = 2; + var end = points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var open = canvas.height * points[i].open/highest - canvas.movedY; + var close = canvas.height * points[i].close/highest - canvas.movedY; + var high = canvas.height * points[i].high/highest - canvas.movedY; + var low = canvas.height * points[i].low/highest - canvas.movedY; + + var top, bottom; + if (close <= open) { + ctx.fillStyle = Qt.rgba(1, 0, 0, 1); + ctx.strokeStyle = Qt.rgba(1, 0, 0, 1); + top = close; + bottom = open; + } else { + ctx.fillStyle = Qt.rgba(0, 1, 0, 1); + ctx.strokeStyle = Qt.rgba(0, 1, 0, 1); + top = open; + bottom = close; + } + + var w1, w2; + w1 = canvas.width/points.length; + w2 = w1 > 10 ? w1/2 : w1; + + ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top); + ctx.beginPath(); + ctx.moveTo(x+w1/2, high); + ctx.lineTo(x+w1/2, low); + ctx.stroke(); + } + ctx.restore(); + } + + function drawVolume(ctx, from, to, color, price, points, highest) + { + ctx.save(); + ctx.fillStyle = color; + ctx.globalAlpha = 0.6; + ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1); + ctx.lineWidth = 1; + + var end = points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var y = points[i][price]; + y = canvas.height * (1 - y/highest); + ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y); + } + ctx.restore(); + } + + onPaint: { + var ctx = canvas.getContext("2d"); + + ctx.globalCompositeOperation = "source-over"; + ctx.lineWidth = 1; + + drawBackground(ctx); + if (!stockModel.ready) + return; + + last = stockModel.indexOf(chart.endDate) + first = last - (chart.endDate.getTime() - chart.startDate.getTime())/86400000; + console.log("painting... first:" + first + ", last:" + last); + + var highestPrice = stockModel.highestPrice; + var highestVolume = stockModel.highestVolume; + console.log("highest price:" + highestPrice + ", highest volume:" + highestVolume) + var points = []; + for (var i = 0; i <= last - first; i++) { + var price = stockModel.get(i + first); + points.push({ + x: i*canvas.width/(last-first+1), + open: price.open, + close: price.close, + high:price.high, + low:price.low, + volume:price.volume + }); + } + if (settings.drawHighPrice) + drawPrice(ctx, first, last, settings.highColor,"high", points, highestPrice); + if (settings.drawLowPrice) + drawPrice(ctx, first, last, settings.lowColor,"low", points, highestPrice); + if (settings.drawOpenPrice) + drawPrice(ctx, first, last,settings.openColor,"open", points, highestPrice); + if (settings.drawClosePrice) + drawPrice(ctx, first, last, settings.closeColor,"close", points, highestPrice); + if (settings.drawVolume) + drawVolume(ctx, first, last, settings.volumeColor,"volume", points, highestVolume); + if (settings.drawKLine) + drawKLine(ctx, first, last, points, highestPrice); + } +} +} diff --git a/examples/demos/stockchart/contents/Stocks.qml b/examples/demos/stockchart/content/StockListModel.qml similarity index 100% rename from examples/demos/stockchart/contents/Stocks.qml rename to examples/demos/stockchart/content/StockListModel.qml diff --git a/examples/demos/stockchart/contents/TitleBar.qml b/examples/demos/stockchart/content/StockListView.qml similarity index 65% rename from examples/demos/stockchart/contents/TitleBar.qml rename to examples/demos/stockchart/content/StockListView.qml index 28edda2..1dd442d 100644 --- a/examples/demos/stockchart/contents/TitleBar.qml +++ b/examples/demos/stockchart/content/StockListView.qml @@ -40,31 +40,48 @@ import QtQuick 2.0 -Item { - id: titleBar - property string title: "" +Rectangle { + id:root + width:320 + height:480 + color:"#423A2F" - BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + property string currentStockId:"" + property string currentStockName:"" - Image { - id: quitButton - anchors.left: parent.left//; anchors.leftMargin: 0 - anchors.verticalCenter: parent.verticalCenter - source: "images/quit.png" - MouseArea { - anchors.fill: parent - onClicked: Qt.quit() - } + ListView { + id:view + anchors.fill:parent + keyNavigationWraps:true + focus:true + snapMode: ListView.SnapToItem + model:StockListModel{} + + onCurrentIndexChanged: { + root.currentStockId = model.get(currentIndex).stockId + root.currentStockName = model.get(currentIndex).name + console.log("current stock:" + root.currentStockId + " - " + root.currentStockName) } - Text { - id: categoryText - anchors { - left: quitButton.right; right: parent.right; //leftMargin: 10; rightMargin: 10 - verticalCenter: parent.verticalCenter + delegate:Rectangle { + height:30 + width:parent.width + color:"transparent" + MouseArea { + anchors.fill: parent + onClicked:view.currentIndex = index + } + + Text { + anchors.verticalCenter : parent.top + anchors.verticalCenterOffset : 15 + color:index == view.currentIndex ? "#ECC089" : "#A58963" + font.pointSize:12 + font.bold:true + text:" " + stockId + " - " + name } - elide: Text.ElideLeft - text: title - font.bold: true; font.pointSize: 20; color: "White"; style: Text.Raised; styleColor: "Black" } -} + + highlight:Image {height:30; width:parent.width; source:"images/stock-selected.png"} + } +} \ No newline at end of file diff --git a/examples/demos/stockchart/content/StockModel.qml b/examples/demos/stockchart/content/StockModel.qml new file mode 100644 index 0000000..72afe28 --- /dev/null +++ b/examples/demos/stockchart/content/StockModel.qml @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListModel { + id:model + property string stockId:"" + property string stockName:"" + property var startDate + property var endDate + property string stockDataCycle:"d" + property bool ready:false + property real stockPrice:0.0 + property real stockPriceChanged:0.0 + property real highestPrice:0 + property real highestVolume:0 + + signal dataReady + + function indexOf(date) { + var end = new Date(model.get(0).date) + var start = new Date(model.get(model.count - 1).date) + if (end <= date) + return model.count -1; + + if (start >= date) + return 0; + + for (var i = 0; i < model.count; i++) { + var d = new Date(model.get(i).date) + if ( d === date) + return i; + } + return -1; + } + + function requestUrl() { + if (stockId === "") + return; + + if (startDate === undefined) + startDate = new Date(1995, 3, 25) //default: 25 April 1995 + + if (endDate === undefined) + endDate = new Date(); //today + + if (stockDataCycle !== "d" && stockDataCycle !== "w" && stockDataCycle !== "m") + stockDataCycle = "d"; + + /* + Fetch stock data from yahoo finance: + url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv + s:stock name/id, a:start day, b:start month, c:start year default: 25 April 1995, oldest c= 1962 + d:end day, e:end month, f:end year, default:today (data only available 3 days before today) + g:data cycle(d daily, w weekly, m monthly, v Dividend) + */ + var request = "http://ichart.finance.yahoo.com/table.csv?"; + request += "s=" + stockId; + request += "&a=" + startDate.getDate(); + request += "&b=" + startDate.getMonth(); + request += "&c=" + startDate.getYear(); + request += "&d=" + endDate.getDate(); + request += "&e=" + endDate.getMonth(); + request += "&f=" + endDate.getYear(); + request += "&g=" + stockDataCycle; + request += "&ignore=.csv"; + return request; + } + + function createStockPrice(r) { + if (highestPrice < r[2]) + highestPrice = r[2]; + if (highestVolume < r[5]) + highestVolume = r[5]; + return { + "date": r[0], + "open":r[1], + "high":r[2], + "low":r[3], + "close":r[4], + "volume":r[5], + "adjusted":r[6] + }; + } + + function updateStock() { + var xhr = new XMLHttpRequest; + + var req = requestUrl(); + console.log("getting " + req + " ....."); + + xhr.open("GET", req); + + + model.ready = false; + model.clear(); + var i = 1; //skip the first line + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) { + var records = xhr.responseText.split('\n'); + console.log("Updating:" + (records.length - i) + " records for " + model.stockId + " from:" + model.startDate + " to " + model.endDate) + + for (;i < records.length; i++ ) { + var r = records[i].split(','); + if (r.length === 7) + model.append(createStockPrice(r)); + } + + if (xhr.readyState === XMLHttpRequest.DONE) { + if (model.count > 0) { + console.log("done, total:" + model.count); + model.ready = true; + model.stockPrice = model.get(0).adjusted + model.stockPriceChanged = Math.round((model.stockPrice - model.get(2).adjusted) * 100) / 100 + model.dataReady(); //emit signal + } + } + } + } + xhr.send() + } +} diff --git a/examples/demos/stockchart/content/StockSettings.qml b/examples/demos/stockchart/content/StockSettings.qml new file mode 100644 index 0000000..656830d --- /dev/null +++ b/examples/demos/stockchart/content/StockSettings.qml @@ -0,0 +1,317 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + id:root + width:320 + height:480 + color:"#423A2F" + property var startDate : startDatePicker.date; + property var endDate : endDatePicker.date; + + property bool drawHighPrice:highButton.buttonEnabled + property bool drawLowPrice:lowButton.buttonEnabled + property bool drawOpenPrice:openButton.buttonEnabled + property bool drawClosePrice:closeButton.buttonEnabled + property bool drawVolume:volumeButton.buttonEnabled + property bool drawKLine:klineButton.buttonEnabled + + property color highColor:Qt.rgba(1, 0, 0, 1) + property color lowColor:Qt.rgba(0, 1, 0, 1) + property color openColor:Qt.rgba(0, 0, 1, 1) + property color closeColor:"#ecc088" + property color volumeColor:Qt.rgba(0.3, 0.5, 0.7, 1) + + property string chartType:"year" + Image { + id:logo + source:"images/logo.png" + anchors.horizontalCenter : parent.horizontalCenter + anchors.top:parent.top + anchors.topMargin:15 + } + + Text { + id:startDateText + text:"START DATE:" + color:"#76644A" + font.pointSize:15 + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:logo.bottom + anchors.topMargin:20 + } + + DatePicker { + id:startDatePicker + anchors.left:parent.left + anchors.leftMargin:30 + anchors.top:startDateText.bottom + anchors.topMargin:15 + date : new Date(1995, 3, 25) + } + + Text { + id:endDateText + text:"END DATE:" + color:"#76644A" + font.pointSize:15 + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:startDatePicker.bottom + anchors.topMargin:20 + } + + DatePicker { + id:endDatePicker + anchors.left:parent.left + anchors.leftMargin:30 + anchors.top:endDateText.bottom + anchors.topMargin:15 + } + + Text { + id:drawOptionsText + text:"DRAW OPTIONS:" + color:"#76644A" + font.pointSize:15 + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:endDatePicker.bottom + anchors.topMargin:20 + } + Column { + id:drawOptions + anchors.top:drawOptionsText.bottom + anchors.topMargin: 20 + anchors.left: parent.left + anchors.leftMargin: 30 + spacing:2 + Row{ + spacing:10 + Text { + text:"High " + color:"#76644A" + font.pointSize:15 + } + + Button { + id:highButton + buttonEnabled:false + } + + Text { + text:"Low " + color:"#76644A" + font.pointSize:15 + } + + Button { + id:lowButton + buttonEnabled:false + } + + Text { + text:"Open " + color:"#76644A" + font.pointSize:15 + } + Button { + id:openButton + buttonEnabled:false + } + } + Row{ + spacing:10 + Text { + text:"Close " + color:"#76644A" + font.pointSize:15 + } + Button { + id:closeButton + buttonEnabled:true + } + Text { + text:"Volume" + color:"#76644A" + font.pointSize:15 + } + Button { + id:volumeButton + buttonEnabled:true + } + Text { + text:"K Line" + color:"#76644A" + font.pointSize:15 + } + Button { + id:klineButton + buttonEnabled:false + } + } + } + + + Text { + id:chartTypeText + text:"CHART TYPE:" + color:"#76644A" + font.pointSize:15 + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:drawOptions.bottom + anchors.topMargin:20 + } + Row { + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top : chartTypeText.bottom + anchors.topMargin: 20 + spacing:10 + Rectangle { + id:yearView + width:70 + height:30 + radius:10 + color:"steelblue" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.fill: parent + font.pointSize: 15 + text:"YEAR" + } + MouseArea { + anchors.fill: parent + onClicked: { + if (root.chartType != "year") { + root.chartType = "year"; + yearView.color = "steelblue" + monthView.color = "gray" + weekView.color = "gray" + allView.color = "gray" + } + } + } + } + Rectangle { + id:monthView + width:70 + radius:10 + height:30 + color:"gray" + Text { + anchors.fill: parent + anchors.horizontalCenter: parent.horizontalCenter + font.pointSize: 15 + color:"#ecc089" + text:"MONTH" + } + MouseArea { + anchors.fill: parent + onClicked: { + if (root.chartType != "month") { + root.chartType = "month"; + yearView.color = "gray" + monthView.color = "steelblue" + weekView.color = "gray" + allView.color = "gray" + } + } + } + + } + Rectangle { + id:weekView + height:30 + width:70 + radius:10 + color:"gray" + Text { + anchors.fill: parent + anchors.horizontalCenter: parent.horizontalCenter + font.pointSize: 15 + color:"#ecc089" + text:"WEEK" + } + MouseArea { + anchors.fill: parent + onClicked: { + if (root.chartType != "week") { + root.chartType = "week"; + yearView.color = "gray" + monthView.color = "gray" + weekView.color = "steelblue" + allView.color = "gray" + } + } + } + } + Rectangle { + id:allView + width:70 + radius:10 + height:30 + color:"gray" + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.fill: parent + font.pointSize: 15 + color:"#ecc089" + text:"ALL" + } + MouseArea { + anchors.fill: parent + onClicked: { + if (root.chartType != "all") { + root.chartType = "all"; + yearView.color = "gray" + monthView.color = "gray" + weekView.color = "gray" + allView.color = "steelblue" + } + } + } + } + } +} diff --git a/examples/demos/stockchart/content/StockView.qml b/examples/demos/stockchart/content/StockView.qml new file mode 100644 index 0000000..7c5ff92 --- /dev/null +++ b/examples/demos/stockchart/content/StockView.qml @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +Rectangle { + id:root + width:320 + height:480 + color:"#423A2F" + property var stock:null + property var stocklist:null + property var settings:null + signal listViewClicked + signal settingsClicked + + function update() { + chart.endDate = settings.endDate + chart.update() + } + + Rectangle { + color:"#272822" + anchors.fill:parent + radius:20 + + Image { + source:"images/icon-items.png" + anchors.left:parent.left + anchors.leftMargin:10 + anchors.top:parent.top + anchors.topMargin:10 + MouseArea { + anchors.fill:parent + onClicked:listViewClicked() + } + } + Image { + source:"images/icon-settings.png" + anchors.right:parent.right + anchors.rightMargin:10 + anchors.top:parent.top + anchors.topMargin:10 + MouseArea { + anchors.fill:parent + onClicked:settingsClicked() + } + } + + Text { + id:desc + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:parent.top + anchors.topMargin:40 + color:"#564c3A" + font.pointSize:15 + text:root.stock.stockId + " - " + root.stock.stockName + } + + Text { + id:price + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:desc.bottom + anchors.topMargin:5 + color:"#ECC089" + font.pointSize:30 + text:root.stock.stockPrice + } + + Text { + id:priceChange + anchors.left:parent.left + anchors.leftMargin:20 + anchors.top:price.bottom + anchors.topMargin:5 + color: root.stock.stockPriceChanged < 0 ? "#A43D3D" : "#679B3A" + font.pointSize:25 + text: root.stock.stockPriceChanged + " (" + Math.abs(Math.round(root.stock.stockPriceChanged/(root.stock.stockPrice - root.stock.stockPriceChanged) * 100))/100 +"%)" + } + + StockChart { + id:chart + anchors.bottom: parent.bottom + anchors.top : priceChange.bottom + anchors.topMargin: 30 + width:parent.width + stockModel:root.stock + settings:root.settings + } + } +} diff --git a/examples/demos/stockchart/content/images/icon-calendar-anim.png b/examples/demos/stockchart/content/images/icon-calendar-anim.png new file mode 100644 index 0000000..c5164d5 Binary files /dev/null and b/examples/demos/stockchart/content/images/icon-calendar-anim.png differ diff --git a/examples/demos/stockchart/content/images/icon-calendar.png b/examples/demos/stockchart/content/images/icon-calendar.png new file mode 100644 index 0000000..bd28574 Binary files /dev/null and b/examples/demos/stockchart/content/images/icon-calendar.png differ diff --git a/examples/demos/stockchart/content/images/icon-items.png b/examples/demos/stockchart/content/images/icon-items.png new file mode 100644 index 0000000..f951aa5 Binary files /dev/null and b/examples/demos/stockchart/content/images/icon-items.png differ diff --git a/examples/demos/stockchart/content/images/icon-settings.png b/examples/demos/stockchart/content/images/icon-settings.png new file mode 100644 index 0000000..222d998 Binary files /dev/null and b/examples/demos/stockchart/content/images/icon-settings.png differ diff --git a/examples/demos/stockchart/content/images/logo.png b/examples/demos/stockchart/content/images/logo.png new file mode 100644 index 0000000..90c7c3b Binary files /dev/null and b/examples/demos/stockchart/content/images/logo.png differ diff --git a/examples/demos/stockchart/content/images/stock-selected.png b/examples/demos/stockchart/content/images/stock-selected.png new file mode 100644 index 0000000..5629796 Binary files /dev/null and b/examples/demos/stockchart/content/images/stock-selected.png differ diff --git a/examples/demos/stockchart/content/images/wheel-touch.png b/examples/demos/stockchart/content/images/wheel-touch.png new file mode 100644 index 0000000..11c8120 Binary files /dev/null and b/examples/demos/stockchart/content/images/wheel-touch.png differ diff --git a/examples/demos/stockchart/content/images/wheel.png b/examples/demos/stockchart/content/images/wheel.png new file mode 100644 index 0000000..470a675 Binary files /dev/null and b/examples/demos/stockchart/content/images/wheel.png differ diff --git a/examples/demos/stockchart/contents/images/quit.png b/examples/demos/stockchart/contents/images/quit.png deleted file mode 100755 index 5bda1b6..0000000 Binary files a/examples/demos/stockchart/contents/images/quit.png and /dev/null differ diff --git a/examples/demos/stockchart/contents/images/stripes.png b/examples/demos/stockchart/contents/images/stripes.png deleted file mode 100755 index 9f36727e..0000000 Binary files a/examples/demos/stockchart/contents/images/stripes.png and /dev/null differ diff --git a/examples/demos/stockchart/contents/Button.qml b/examples/demos/stockchart/main.qml similarity index 60% rename from examples/demos/stockchart/contents/Button.qml rename to examples/demos/stockchart/main.qml index ab9ce35..e3cdedc 100644 --- a/examples/demos/stockchart/contents/Button.qml +++ b/examples/demos/stockchart/main.qml @@ -39,49 +39,63 @@ ****************************************************************************/ import QtQuick 2.0 +import "./content" -Item { - id: container +ListView { + id:root + width:320 + height:480 + snapMode:ListView.SnapOneItem + focus:false + orientation : ListView.Horizontal + boundsBehavior : Flickable.StopAtBounds + currentIndex : 1 - signal clicked - - property string text - width: buttonText.width + 28 - height: buttonText.height + 14 - - BorderImage { - id: buttonImage - source: "images/toolbutton.sci" - width: container.width - 10 - height: container.height + StockModel { + id:stock + stockId:listView.currentStockId + stockName: listView.currentStockName + startDate: settings.startDate + endDate:settings.endDate + onStockIdChanged: updateStock() + onStartDateChanged: updateStock() + onEndDateChanged: updateStock() + onDataReady: { + root.currentIndex = 1 + stockView.update() } - BorderImage { - id: pressed - opacity: 0 - source: "images/toolbutton.sci" - width: container.width - 10 - height: container.height + } + + model: VisualItemModel { + StockListView { + id:listView + width:root.width + height:root.height } - MouseArea { - id: mouseRegion - anchors.fill: buttonImage - onClicked: { container.clicked(); } + + StockView { + id:stockView + width:root.width + height:root.height + stocklist : listView + settings : settings + stock: stock + + onListViewClicked:root.currentIndex = 0 + onSettingsClicked:root.currentIndex = 2 } - Text { - id: buttonText - color: "white" - anchors.centerIn: buttonImage - font.bold: true - font.pointSize: 15 - text: container.text - style: Text.Raised - styleColor: "black" + + StockSettings { + id:settings + width:root.width + height:root.height + onDrawHighPriceChanged: stockView.update() + onDrawLowPriceChanged: stockView.update() + onDrawOpenPriceChanged: stockView.update() + onDrawClosePriceChanged: stockView.update() + onDrawVolumeChanged: stockView.update() + onDrawKLineChanged: stockView.update() + onChartTypeChanged: stockView.update() } - states: [ - State { - name: "Pressed" - when: mouseRegion.pressed == true - PropertyChanges { target: pressed; opacity: 1 } - } - ] + } } diff --git a/examples/demos/stockchart/model.cpp b/examples/demos/stockchart/model.cpp deleted file mode 100644 index 42eb2d5..0000000 --- a/examples/demos/stockchart/model.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "model.h" - -#include -#include -#include -#include -#include - -#include -#include - -StockModel::StockModel(QObject *parent) - : QAbstractListModel(parent) - , _startDate(QDate(1995, 4, 25)) - , _endDate(QDate::currentDate()) - , _dataCycle(StockModel::Daily) - , _manager(0) - , _updating(false) -{ - QHash roles; - roles[StockModel::DateRole] = "date"; - roles[StockModel::SectionRole] = "year"; - roles[StockModel::OpenPriceRole] = "openPrice"; - roles[StockModel::ClosePriceRole] = "closePrice"; - roles[StockModel::HighPriceRole] = "highPrice"; - roles[StockModel::LowPriceRole] = "lowPrice"; - roles[StockModel::VolumeRole] = "volume"; - roles[StockModel::AdjustedPriceRole] = "adjustedPrice"; - setRoleNames(roles); - - connect(this, SIGNAL(stockNameChanged()), SLOT(requestData())); - connect(this, SIGNAL(startDateChanged()), SLOT(requestData())); - connect(this, SIGNAL(endDateChanged()), SLOT(requestData())); - connect(this, SIGNAL(dataCycleChanged()), SLOT(requestData())); - - _manager = new QNetworkAccessManager(this); - connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(update(QNetworkReply*))); - -} - -int StockModel::rowCount(const QModelIndex & parent) const { - Q_UNUSED(parent); - return _prices.count(); -} - -StockPrice* StockModel::stockPriceAtIndex(int idx) const -{ - if (idx >=0 && idx < _prices.size()) { - return _prices[idx]; - } - return 0; -} - - -void StockModel::requestData() -{ - if (!_updating) { - _updating = true; - QMetaObject::invokeMethod(this, "doRequest", Qt::QueuedConnection); - } -} - -void StockModel::doRequest() -{ - /* - Fetch stock data from yahoo finance: - url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv - s:stock name/id, a:start day, b:start month, c:start year default: 25 April 1995, oldest c= 1962 - d:end day, e:end month, f:end year, default:today (data only available 3 days before today) - g:data cycle(d daily, w weekly, m monthly, v Dividend) - */ - if (_manager && !_stockName.isEmpty() && _endDate > _startDate) { - QString query("http://ichart.finance.yahoo.com/table.csv?s=%1&a=%2&b=%3&c=%4&d=%5&e=%6&f=%7&g=%8&ignore=.csv"); - query = query.arg(_stockName) - .arg(_startDate.day()).arg(_startDate.month()).arg(_startDate.year()) - .arg(_endDate.day()).arg(_endDate.month()).arg(_endDate.year()) - .arg(dataCycleString()); - - qDebug() << "request stock data:" << query; - QNetworkReply* reply = _manager->get(QNetworkRequest(QUrl(query))); - connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(downloadProgress(qint64,qint64))); - } -} - -void StockModel::update(QNetworkReply *reply) -{ - _updating = false; - - if (reply) { - if (reply->error() == QNetworkReply::NoError) { - beginResetModel(); - - foreach (StockPrice* p, _prices) { - p->deleteLater(); - } - - _prices.clear(); - - while (!reply->atEnd()) { - QString line = reply->readLine(); - QStringList fields = line.split(','); - - //data format:Date,Open,High,Low,Close,Volume,Adjusted close price - //example: 2011-06-24,6.03,6.04,5.88,5.88,20465200,5.88 - if (fields.size() == 7) { - StockPrice* price = new StockPrice(this); - price->setDate(QDate::fromString(fields[0], Qt::ISODate)); - price->setOpenPrice(fields[1].toFloat()); - price->setHighPrice(fields[2].toFloat()); - price->setLowPrice(fields[3].toFloat()); - price->setClosePrice(fields[4].toFloat()); - price->setVolume(fields[5].toInt()); - price->setAdjustedPrice(fields[6].toFloat()); - _prices.prepend(price); - } - } - qDebug() << "get stock data successfully, total:" << _prices.count() << "records."; - } else { - qDebug() << "get stock data failed:" << reply->errorString(); - } - reply->deleteLater(); - endResetModel(); - emit dataChanged(QModelIndex(), QModelIndex()); - } -} - -QVariant StockModel::data(const QModelIndex & index, int role) const { - if (index.row() < 0 || index.row() > _prices.count()) - return QVariant(); - - const StockPrice* price = _prices[index.row()]; - if (role == StockModel::DateRole) - return price->date(); - else if (role == StockModel::OpenPriceRole) - return price->openPrice(); - else if (role == StockModel::ClosePriceRole) - return price->closePrice(); - else if (role == StockModel::HighPriceRole) - return price->highPrice(); - else if (role == StockModel::LowPriceRole) - return price->lowPrice(); - else if (role == StockModel::AdjustedPriceRole) - return price->adjustedPrice(); - else if (role == StockModel::VolumeRole) - return price->volume(); - else if (role == StockModel::SectionRole) - return price->date().year(); - return QVariant(); -} - -QString StockModel::stockName() const -{ - return _stockName; -} -void StockModel::setStockName(const QString& name) -{ - if (_stockName != name) { - _stockName = name; - emit stockNameChanged(); - } -} - -QDate StockModel::startDate() const -{ - return _startDate; -} -void StockModel::setStartDate(const QDate& date) -{ - if (_startDate.isValid() && _startDate != date) { - _startDate = date; - emit startDateChanged(); - } -} - -QDate StockModel::endDate() const -{ - return _endDate; -} -void StockModel::setEndDate(const QDate& date) -{ - if (_endDate.isValid() && _endDate != date) { - _endDate = date; - emit endDateChanged(); - } -} - -StockModel::StockDataCycle StockModel::dataCycle() const -{ - return _dataCycle; -} - -QString StockModel::dataCycleString() const -{ - switch (_dataCycle) { - case StockModel::Daily: - return QString('d'); - break; - case StockModel::Weekly: - return QString('w'); - case StockModel::Monthly: - return QString('m'); - case StockModel::Dividend: - return QString('v'); - } - - return QString('d'); -} - - -void StockModel::setDataCycle(StockModel::StockDataCycle cycle) -{ - if (_dataCycle != cycle) { - _dataCycle = cycle; - emit dataCycleChanged(); - } -} diff --git a/examples/demos/stockchart/model.h b/examples/demos/stockchart/model.h deleted file mode 100644 index 95e6f48..0000000 --- a/examples/demos/stockchart/model.h +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include - -class StockPrice : public QObject -{ - Q_OBJECT - Q_PROPERTY(QDate date READ date) - Q_PROPERTY(qreal openPrice READ openPrice) - Q_PROPERTY(qreal closePrice READ closePrice) - Q_PROPERTY(qreal highPrice READ highPrice) - Q_PROPERTY(qreal lowPrice READ lowPrice) - Q_PROPERTY(qint32 volume READ volume) - Q_PROPERTY(qreal adjustedPrice READ adjustedPrice) -public: - - StockPrice(QObject *parent = 0) - : QObject(parent) - , _openPrice(-1) - , _closePrice(-1) - , _highPrice(-1) - , _lowPrice(-1) - , _volume(-1) - , _adjustedPrice(-1) - { - } - QDate date() const {return _date;} - qreal openPrice() const {return _openPrice; } - qreal closePrice() const {return _closePrice;} - qreal highPrice() const {return _highPrice;} - qreal lowPrice() const{return _lowPrice;} - qreal adjustedPrice() const{return _adjustedPrice;} - qint32 volume() const{return _volume;} - - void setDate(const QDate& date){_date = date;} - void setOpenPrice(qreal price){_openPrice = price;} - void setClosePrice(qreal price){_closePrice = price;} - void setHighPrice(qreal price){_highPrice = price;} - void setLowPrice(qreal price){_lowPrice = price;} - void setAdjustedPrice(qreal price) {_adjustedPrice = price;} - void setVolume(qint32 volume) {_volume = volume;} - -private: - QDate _date; - qreal _openPrice; - qreal _closePrice; - qreal _highPrice; - qreal _lowPrice; - qint32 _volume; - qreal _adjustedPrice; -}; - -class QNetworkReply; -class QNetworkAccessManager; -class StockModel : public QAbstractListModel -{ - Q_OBJECT - - Q_PROPERTY(QString stockName READ stockName WRITE setStockName NOTIFY stockNameChanged) - Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) - Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged) - Q_PROPERTY(StockDataCycle dataCycle READ dataCycle WRITE setDataCycle NOTIFY dataCycleChanged) - - Q_ENUMS(StockDataCycle) -public: - enum StockDataCycle { - Daily, - Weekly, - Monthly, - Dividend - }; - - enum StockModelRoles { - DateRole = Qt::UserRole + 1, - SectionRole, - OpenPriceRole, - ClosePriceRole, - HighPriceRole, - LowPriceRole, - VolumeRole, - AdjustedPriceRole - }; - - StockModel(QObject *parent = 0); - - QString stockName() const; - void setStockName(const QString& name); - - QDate startDate() const; - void setStartDate(const QDate& date); - - QDate endDate() const; - void setEndDate(const QDate& date); - - StockDataCycle dataCycle() const; - void setDataCycle(StockDataCycle cycle); - - int rowCount(const QModelIndex & parent = QModelIndex()) const; - - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; - -signals: - void stockNameChanged(); - void startDateChanged(); - void endDateChanged(); - void dataCycleChanged(); - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - -public slots: - void requestData(); - StockPrice* stockPriceAtIndex(int idx) const; -private slots: - void doRequest(); - void update(QNetworkReply* reply); -private: - QString dataCycleString() const; - QList _prices; - QString _stockName; - QDate _startDate; - QDate _endDate; - StockDataCycle _dataCycle; - QNetworkAccessManager* _manager; - bool _updating; -}; - - - - diff --git a/examples/demos/stockchart/plugin.cpp b/examples/demos/stockchart/plugin.cpp deleted file mode 100644 index 3b354e2..0000000 --- a/examples/demos/stockchart/plugin.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "model.h" - -class QStockChartExampleQmlPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT -public: - void registerTypes(const char *uri) - { - Q_ASSERT(uri == QLatin1String("com.nokia.StockChartExample")); - qmlRegisterType(uri, 1, 0, "StockModel"); - qmlRegisterType(uri, 1, 0, "StockPrice"); - } -}; - -#include "plugin.moc" - -Q_EXPORT_PLUGIN2(qmlstockchartexampleplugin, QStockChartExampleQmlPlugin); diff --git a/examples/demos/stockchart/stock.qml b/examples/demos/stockchart/stock.qml deleted file mode 100644 index 819625c..0000000 --- a/examples/demos/stockchart/stock.qml +++ /dev/null @@ -1,726 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.0 -import com.nokia.StockChartExample 1.0 -import "./contents" - -Rectangle { - id:container - width: 360; height: 600 - color: "#343434"; - Image { source: "contents/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 1 } - - - TitleBar { - id: titleBar - width: parent.width - anchors.top : container.top - height: 40 - opacity: 0.9 - } - - StockModel { - id:stockModel - dataCycle: StockModel.Daily - function dataCycleName() { - if (dataCycle === StockModel.Weekly) - return "Weekly"; - else if (dataCycle === StockModel.Monthly) - return "Monthly"; - return "Daily"; - } - - onDataChanged: { - if (view.viewType == "chart") { - canvas.requestPaint(); - } - } - onDownloadProgress: { - if (bytesReceived == bytesTotal && bytesTotal != -1) { - progress.opacity = 0; - } else { - progress.opacity = 0.8; - progress.text = "downloading " + stockModel.dataCycleName() + " data ..."+ Math.round(bytesReceived/1000) + " KB"; - } - } - - property string description:""; - } - - Stocks {id:stocks} - - Rectangle { - id: header - width: parent.width - height: 20 - color: "steelblue" - opacity: 0 - Row { - spacing: 2 - Text { - id:t - font.pointSize:15 - horizontalAlignment:Text.AlignHCenter - font.bold: true - font.underline:true - } - Rectangle { - height:20 - width:50 - Text {text:"Stock list"; font.pointSize:15; font.bold: true} - } - } - } - - ListView { - id:stockList - width: parent.width - anchors.bottom: container.bottom - anchors.top : titleBar.bottom - focus: true - keyNavigationWraps: true - spacing:1 - opacity: 1 - model: stocks - - Component.onCompleted: opacity = 0.9; - onOpacityChanged: { - titleBar.title = "Top 100 NASDAQ stocks" - } - - - delegate : Rectangle { - height: 30 - width: view.width - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - Text { - font.pointSize:20 - text: index + ". " + stockId + " \t(" + name + ")"; - } - MouseArea { - anchors.fill: parent; - onDoubleClicked: { - stockList.opacity = 0; - stockModel.stockName = stockId; - stockModel.description = "NASDAQ:" + stockId + " (" + name + ")"; - view.opacity = 1; - view.viewType = "chart"; - canvas.opacity = 0.7; - } - onClicked: stockList.currentIndex = index - }//mousearea - }//delegate - } - - ListView { - id:view - width: container.width - height: container.height - 50 - anchors.bottom: container.bottom - focus: true - keyNavigationWraps: true - - spacing:1 - opacity: 0 - model: stockModel - highlightFollowsCurrentItem: false - highlightRangeMode: ListView.StrictlyEnforceRange - preferredHighlightBegin:50 - preferredHighlightEnd : height - 50 - highlight: listHighlight - - //header : Text {} - delegate: listDelegate - snapMode: ListView.SnapToItem - - property string viewType : "list" - property int topIndex:indexAt(0,contentY); - property int bottomIndex:indexAt(0, contentY+height); - - onCountChanged: { - - titleBar.title = stockModel.description + " " + Qt.formatDate(stockModel.startDate, "yyyy-MM-dd") + " - " + - Qt.formatDate(stockModel.endDate, "yyyy-MM-dd") + " " + stockModel.dataCycleName() + - " records:" + view.count; - - } - - Component { - id: listDelegate - Rectangle { - height: 20 - width: view.width - border.color: "lightsteelblue" - border.width: 1 - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - Text { - font.pointSize:13 - text: index + ". " + Qt.formatDate(date, "yyyy-MM-dd") - + "\t " + Math.round(openPrice*100)/100 - + "\t " + Math.round(highPrice*100)/100 - + "\t " + Math.round(lowPrice*100)/100 - + "\t " + Math.round(closePrice*100)/100 - + "\t " + volume + "\t " - + Math.round(adjustedPrice*100)/100; - } - MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} - } - } - - Component { - id: chartDelegate - Rectangle { - height: 20 - width: view.width/view.count * canvas.scaleX - border.color: "lightsteelblue" - border.width: 1 - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - - Text { - anchors.bottom: parent.bottom - font.pointSize: { - if (parent.width <= 4) - return 1; - if (parent.width <= 50) - return parent.width/4; - return 15; - } - horizontalAlignment:Text.AlignHCenter - verticalAlignment:Text.AlignBottom - text:font.pointSize > 1 ? Qt.formatDate(date, "d/M/yy") : "" - } - MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} - } - } - - Component { - id:chartHighlight - Rectangle { radius: 5; width:40; height: 20; color: "lightsteelblue" } - } - - Component { - id:listHighlight - Rectangle { radius: 5; width:container.width; height: 20; color: "lightsteelblue" } - } - - - - - onViewTypeChanged : { - if (viewType == "list") { - view.orientation = ListView.Vertical; - view.delegate = listDelegate; -// view.section.property = "year"; -// view.section.criteria = ViewSection.FullString; -// view.section.delegate = sectionHeading; - view.highlight = listHighlight; - view.opacity = 1; - canvas.opacity = 0; - // comment.opacity = 0; - - } else if (viewType == "chart") { - view.orientation = ListView.Horizontal; - view.delegate = chartDelegate; - //comment.opacity = 0.6; - - view.opacity = 1; - view.height = 30 - - canvas.opacity = 0.7; - canvas.requestPaint(); - } else { - viewType = "list"; - } - } - - - onCurrentIndexChanged: { - //header.updateCurrent(stockModel.stockPriceAtIndex(view.currentIndex)); - if (viewType == "chart") { - canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); - canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); - - canvas.requestPaint(); - } - } - onContentYChanged: { // keep "current" item visible - topIndex = indexAt(0,contentY); - bottomIndex = indexAt(0, contentY+height); - - if (topIndex != -1 && currentIndex <= topIndex) - currentIndex = topIndex+1; - else if (bottomIndex != -1 && currentIndex >= bottomIndex) - currentIndex = bottomIndex-1; - if (viewType == "chart") - canvas.requestPaint(); - } - - onContentXChanged: { // keep "current" item visible - topIndex = indexAt(contentX,0); - bottomIndex = indexAt(contentX+width, 0); - - if (topIndex != -1 && currentIndex <= topIndex) - currentIndex = topIndex+1; - else if (bottomIndex != -1 && currentIndex >= bottomIndex) - currentIndex = bottomIndex-1; - if (viewType == "chart") - canvas.requestPaint(); - } - - MouseArea { - anchors.fill: parent - onDoubleClicked: { - if (view.viewType == "list") - view.viewType = "chart"; - else - view.viewType = "list"; - } - } - } - - - - Canvas { - id:canvas - anchors.top : titleBar.bottom - anchors.bottom : view.top - width:container.width; - opacity:0 - renderTarget: Canvas.Image - renderStrategy: Canvas.Immediate - property bool running:false - property int frames:first - property int mouseX:0; - property int mouseY:0; - property int mousePressedX:0; - property int mousePressedY:0; - property int movedY:0 - property real scaleX:1.0; - property real scaleY:1.0; - property int first:0; - property int last:view.count - 1; - - onOpacityChanged: { - if (opacity > 0) - requestPaint(); - } - Text { - id:comment - x:100 - y:50 - font.pointSize: 20 - color:"white" - opacity: 0.7 - focus:false - text: stockModel.description - function updateCurrent(price) - { - if (price !== undefined) { - text =stockModel.description + "\n" - + Qt.formatDate(price.date, "yyyy-MM-dd") + " OPEN:" - + Math.round(price.openPrice*100)/100 + " HIGH:" - + Math.round(price.highPrice*100)/100 + " LOW:" - + Math.round(price.lowPrice*100)/100 + " CLOSE:" - + Math.round(price.closePrice*100)/100 + " VOLUME:" - + price.volume; - } - } - } - - Text { - id:priceAxis - x:25 - y:25 - font.pointSize: 15 - color:"yellow" - opacity: 0.7 - focus: false - } - Text { - id:volumeAxis - x:canvas.width - 200 - y:25 - font.pointSize: 15 - color:"yellow" - opacity: 0.7 - } - - Rectangle { - id:progress - x:canvas.width/2 - 100 - y:canvas.height/2 - width:childrenRect.width - height: childrenRect.height - opacity: 0 - color:"white" - property string text; - Text { - text:parent.text - font.pointSize: 20 - } - } - - Button { - id:runButton - text:"Run this chart" - y:0 - x:canvas.width/2 - 50 - opacity: 0.5 - onClicked: { - if (canvas.running) { - canvas.running = false; - canvas.frames = canvas.first; - canvas.requestPaint(); - text = "Run this chart"; - comment.text = stockModel.description; - } else { - text = " Stop running "; - canvas.runChart(); - } - } - } - Button { - id:returnButton - text:"Stocks" - y:0 - anchors.left : runButton.right - anchors.leftMargin : 20 - opacity: 0.5 - onClicked: { - stockList.opacity = 1; - canvas.opacity = 0; - } - } - PinchArea { - anchors.fill: parent - onPinchUpdated : { - var current = pinch.center; - var scale = pinch.scale; - console.log("center:" + pinch.center + " scale:" + pinch.scale); - //canvas.requestPaint(); - } - } - - MouseArea { - anchors.fill: parent - - onDoubleClicked: { - if (stockModel.dataCycle == StockModel.Daily) - stockModel.dataCycle = StockModel.Weekly; - else if (stockModel.dataCycle == StockModel.Weekly) - stockModel.dataCycle = StockModel.Monthly; - else - stockModel.dataCycle = StockModel.Daily; - } - - onPositionChanged: { - if (mouse.modifiers & Qt.ControlModifier) { - if (canvas.mouseX == 0 && canvas.mouseY == 0) { - canvas.mouseX = mouse.x; - canvas.mouseY = mouse.y; - } - } else{ - var w = (view.width/view.count)*canvas.scaleX; - - //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2); - - var movedX = Math.round((canvas.mousePressedX - mouse.x)/w); - if (movedX != 0 || canvas.movedY != 0) { - if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) { - canvas.first += movedX; - canvas.last += movedX; - } - canvas.requestPaint(); - } - } - } - - onPressed: { - canvas.mousePressedX = mouse.x; - canvas.mousePressedY = mouse.y; - } - - onReleased : { - if (mouse.modifiers & Qt.ControlModifier) { - var sx = mouse.x - canvas.mouseX; - var sy = canvas.mouseY - mouse.y; - - if (Math.abs(sx) < 50) sx = 0; - if (Math.abs(sy) < 50) sy = 0; - - if (sx > 0) - canvas.scaleX *= sx/100 +1; - else - canvas.scaleX *= 1/(-sx/100 + 1); - - if (sy > 0) - canvas.scaleY *= sy/100 +1; - else - canvas.scaleY *= 1/(-sy/100 + 1); - - if (canvas.scaleX < 1) - canvas.scaleX = 1; - - //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY); - - canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); - canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); - - canvas.mouseX = 0; - canvas.mouseY = 0; - canvas.mousePressedX = 0; - canvas.mousePressedY = 0; - canvas.requestPaint(); - } - } - } - - function runChart() { - canvas.running = true; - requestPaint(); - } - - function showPriceAt(x) { - var w = (view.width/view.count)*canvas.scaleX; - //header.updateCurrent(stockModel.stockPriceAtIndex(canvas.first + Math.round(x/w))); - //console.log("x:" + x + " w:" + w + " index:" + (canvas.first + Math.round(x/w))); - } - - function drawPrice(ctx, from, to, color, price, points, highest) - { - ctx.globalAlpha = 0.7; - ctx.strokeStyle = color; - ctx.lineWidth = 1; - ctx.beginPath(); - - //price x axis - priceAxis.text = "price:" + Math.round(highest); - ctx.font = "bold 12px sans-serif"; - - ctx.strokeText("price", 25, 25); - for (var j = 1; j < 30; j++) { - var val = (highest * j) / 30; - val = canvas.height * (1 - val/highest); - ctx.beginPath(); - - ctx.moveTo(10, val); - if (j % 5) - ctx.lineTo(15, val); - else - ctx.lineTo(20, val); - ctx.stroke(); - } - - ctx.beginPath(); - ctx.moveTo(10, 0); - ctx.lineTo(10, canvas.height); - ctx.stroke(); - - - var w = canvas.width/points.length; - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var y = points[i][price]; - y += canvas.movedY; - - y = canvas.height * (1 - y/highest); - if (i == 0) { - ctx.moveTo(x+w/2, y); - } else { - ctx.lineTo(x+w/2, y); - } - } - ctx.stroke(); - } - - function drawKLine(ctx, from, to, points, highest) - { - ctx.globalAlpha = 0.4; - ctx.lineWidth = 2; - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var open = canvas.height * (1 - points[i].open/highest) - canvas.movedY; - var close = canvas.height * (1 - points[i].close/highest) - canvas.movedY; - var high = canvas.height * (1 - points[i].high/highest) - canvas.movedY; - var low = canvas.height * (1 - points[i].low/highest) - canvas.movedY; - - var top, bottom; - if (close <= open) { - ctx.fillStyle = Qt.rgba(1, 0, 0, 1); - ctx.strokeStyle = Qt.rgba(1, 0, 0, 1); - top = close; - bottom = open; - } else { - ctx.fillStyle = Qt.rgba(0, 1, 0, 1); - ctx.strokeStyle = Qt.rgba(0, 1, 0, 1); - top = open; - bottom = close; - } - - var w1, w2; - w1 = canvas.width/points.length; - w2 = w1 > 10 ? w1/2 : w1; - - ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top); - ctx.beginPath(); - ctx.moveTo(x+w1/2, high); - ctx.lineTo(x+w1/2, low); - ctx.stroke(); - } - ctx.globalAlpha = 1; - - } - - function drawVolume(ctx, from, to, color, price, points, highest) - { - ctx.fillStyle = color; - ctx.globalAlpha = 0.6; - ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1); - ctx.lineWidth = 1; - - //volume x axis - volumeAxis.text = "volume:" + Math.round(highest/(1000*100)) + "M"; - for (var j = 1; j < 30; j++) { - var val = (highest * j) / 30; - val = canvas.height * (1 - val/highest); - ctx.beginPath(); - if (j % 5) - ctx.moveTo(canvas.width - 15, val); - else - ctx.moveTo(canvas.width - 20, val); - ctx.lineTo(canvas.width - 10, val); - ctx.stroke(); - } - - ctx.beginPath(); - ctx.moveTo(canvas.width - 10, 0); - ctx.lineTo(canvas.width - 10, canvas.height); - ctx.stroke(); - - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var y = points[i][price]; - y = canvas.height * (1 - y/highest); - ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y); - } - } -/* - onPainted : { - if (canvas.running) { - if (frames >= last) { - canvas.running = false; - canvas.frames = first; - runButton.text = "Run this chart"; - comment.text = stockModel.description; - requestPaint(); - } else { - frames += Math.round(view.count / 100); - if (frames > last) frames = last; - var price = stockModel.stockPriceAtIndex(frames); - if (price) { - comment.updateCurrent(price); - } - - requestPaint(); - } - } - } -*/ - onPaint: { - if (view.currentIndex <= 0) - first = 0; - if (last >= view.count) - last = view.count - 1; - - //console.log("painting... first:" + first + ", last:" + last + " current:" + view.currentIndex); - var ctx = canvas.getContext("2d"); - ctx.save(); - - ctx.globalCompositeOperation = "source-over"; - ctx.lineWidth = 1; - ctx.lineJoin = "round"; - ctx.fillStyle = "rgba(0,0,0,0)"; - - ctx.fillRect(0, 0, canvas.width, canvas.height); - - - - var highestPrice = 500/canvas.scaleY; - var highestValume = 600 * 1000 * 1000/canvas.scaleY; - var points = []; - for (var i = 0; i <= last - first; i++) { - var price = stockModel.stockPriceAtIndex(i + first); - points.push({ - x: i*canvas.width/(last-first+1), - open: price.openPrice, - close: price.closePrice, - high:price.highPrice, - low:price.lowPrice, - volume:price.volume - }); - } - - drawPrice(ctx, first, last, Qt.rgba(1, 0, 0, 1),"high", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0, 1, 0, 1),"low", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0, 0, 1, 1),"open", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0.5, 0.5, 0.5, 1),"close", points, highestPrice); - drawVolume(ctx, first, last, Qt.rgba(0.3, 0.5, 0.7, 1),"volume", points, highestValume); - drawKLine(ctx, first, last, points, highestPrice); - ctx.restore(); - } - } -} diff --git a/examples/demos/stockchart/stockchart.pro b/examples/demos/stockchart/stockchart.pro deleted file mode 100644 index e368746..0000000 --- a/examples/demos/stockchart/stockchart.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = lib -CONFIG += qt plugin -QT += qml network - -DESTDIR = com/nokia/StockChartExample -TARGET = qmlstockchartexampleplugin - -SOURCES += model.cpp plugin.cpp -HEADERS += model.h -qdeclarativesources.files += \ - com/nokia/StockChartExample/qmldir \ - stock.qml - -qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample - -sources.files += stockchart.pro model.h model.cpp plugin.cpp README -sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins -target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample - -INSTALLS += qdeclarativesources sources target diff --git a/examples/demos/stockchart/stockchart.qmlproject b/examples/demos/stockchart/stockchart.qmlproject deleted file mode 100644 index 5f2b909..0000000 --- a/examples/demos/stockchart/stockchart.qmlproject +++ /dev/null @@ -1,16 +0,0 @@ -import QmlProject 1.1 - -Project { - mainFile: "stock.qml" - - /* Include .qml, .js, and image files from current directory and subdirectories */ - QmlFiles { - directory: "." - } - JavaScriptFiles { - directory: "." - } - ImageFiles { - directory: "." - } -} \ No newline at end of file