From 6b8c356401259675204126897a563cf020bd68f4 Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Wed, 29 Feb 2012 11:48:06 +1000 Subject: [PATCH] Refactor canvas examples by following the new example guidelines. Change-Id: I1cc749ad11b8439239ba739f40e99b78af7351ab Reviewed-by: Yunqiao Yin --- examples/demos/stockchart/README | 5 + .../stockchart/com/nokia/StockChartExample/qmldir | 1 + examples/demos/stockchart/model.cpp | 255 +++++++ examples/demos/stockchart/model.h | 166 +++++ examples/demos/stockchart/plugin.cpp | 60 ++ examples/demos/stockchart/stock.qml | 726 ++++++++++++++++++++ examples/demos/stockchart/stockchart.pro | 20 + examples/demos/stockchart/stockchart.qmlproject | 16 + examples/demos/twitterfriends/TwitterUser.qml | 294 ++++++++ examples/demos/twitterfriends/cache.js | 42 ++ examples/demos/twitterfriends/friends.qml | 140 ++++ .../demos/twitterfriends/twitterfriends.qmlproject | 16 + examples/quick/canvas/bezierCurve/bezierCurve.qml | 24 +- examples/quick/canvas/canvas.pro | 9 + examples/quick/canvas/canvas.qml | 85 +++ examples/quick/canvas/clip/clip.qml | 24 +- examples/quick/canvas/contents/Button.qml | 2 +- examples/quick/canvas/main.cpp | 41 ++ .../canvas/quadraticCurveTo/quadraticCurveTo.qml | 24 +- examples/quick/canvas/roundedrect/roundedrect.qml | 24 +- examples/quick/canvas/smile/smile.qml | 24 +- examples/quick/canvas/squircle/squircle.qml | 24 +- examples/quick/canvas/stockchart/README | 5 - .../stockchart/com/nokia/StockChartExample/qmldir | 1 - examples/quick/canvas/stockchart/model.cpp | 255 ------- examples/quick/canvas/stockchart/model.h | 166 ----- examples/quick/canvas/stockchart/plugin.cpp | 60 -- examples/quick/canvas/stockchart/stock.qml | 726 -------------------- examples/quick/canvas/stockchart/stockchart.pro | 20 - examples/quick/canvas/tiger/tiger.qml | 22 +- .../quick/canvas/twitterfriends/TwitterUser.qml | 294 -------- examples/quick/canvas/twitterfriends/cache.js | 42 -- examples/quick/canvas/twitterfriends/twitter.qml | 141 ---- 33 files changed, 1960 insertions(+), 1794 deletions(-) create mode 100644 examples/demos/stockchart/README create mode 100644 examples/demos/stockchart/com/nokia/StockChartExample/qmldir create mode 100644 examples/demos/stockchart/model.cpp create mode 100644 examples/demos/stockchart/model.h create mode 100644 examples/demos/stockchart/plugin.cpp create mode 100644 examples/demos/stockchart/stock.qml create mode 100644 examples/demos/stockchart/stockchart.pro create mode 100644 examples/demos/stockchart/stockchart.qmlproject create mode 100644 examples/demos/twitterfriends/TwitterUser.qml create mode 100644 examples/demos/twitterfriends/cache.js create mode 100644 examples/demos/twitterfriends/friends.qml create mode 100644 examples/demos/twitterfriends/twitterfriends.qmlproject create mode 100644 examples/quick/canvas/canvas.pro create mode 100644 examples/quick/canvas/canvas.qml create mode 100644 examples/quick/canvas/main.cpp delete mode 100644 examples/quick/canvas/stockchart/README delete mode 100644 examples/quick/canvas/stockchart/com/nokia/StockChartExample/qmldir delete mode 100644 examples/quick/canvas/stockchart/model.cpp delete mode 100644 examples/quick/canvas/stockchart/model.h delete mode 100644 examples/quick/canvas/stockchart/plugin.cpp delete mode 100644 examples/quick/canvas/stockchart/stock.qml delete mode 100644 examples/quick/canvas/stockchart/stockchart.pro delete mode 100644 examples/quick/canvas/twitterfriends/TwitterUser.qml delete mode 100644 examples/quick/canvas/twitterfriends/cache.js delete mode 100644 examples/quick/canvas/twitterfriends/twitter.qml diff --git a/examples/demos/stockchart/README b/examples/demos/stockchart/README new file mode 100644 index 0000000..2652866 --- /dev/null +++ b/examples/demos/stockchart/README @@ -0,0 +1,5 @@ +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 new file mode 100644 index 0000000..4c60e55 --- /dev/null +++ b/examples/demos/stockchart/com/nokia/StockChartExample/qmldir @@ -0,0 +1 @@ +plugin qmlstockchartexampleplugin diff --git a/examples/demos/stockchart/model.cpp b/examples/demos/stockchart/model.cpp new file mode 100644 index 0000000..42eb2d5 --- /dev/null +++ b/examples/demos/stockchart/model.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** 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 new file mode 100644 index 0000000..95e6f48 --- /dev/null +++ b/examples/demos/stockchart/model.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** 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 new file mode 100644 index 0000000..3b354e2 --- /dev/null +++ b/examples/demos/stockchart/plugin.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 new file mode 100644 index 0000000..1c95fde --- /dev/null +++ b/examples/demos/stockchart/stock.qml @@ -0,0 +1,726 @@ +/**************************************************************************** +** +** 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 new file mode 100644 index 0000000..e368746 --- /dev/null +++ b/examples/demos/stockchart/stockchart.pro @@ -0,0 +1,20 @@ +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 new file mode 100644 index 0000000..5f2b909 --- /dev/null +++ b/examples/demos/stockchart/stockchart.qmlproject @@ -0,0 +1,16 @@ +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 diff --git a/examples/demos/twitterfriends/TwitterUser.qml b/examples/demos/twitterfriends/TwitterUser.qml new file mode 100644 index 0000000..8b90621 --- /dev/null +++ b/examples/demos/twitterfriends/TwitterUser.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** 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 + +Item { + id:twitterUser + property variant friends : []; + property string name : ""; + property string twitterId : ""; + property string image : ""; + property string url : ""; + property string desc : ""; + width : 0; + height : 0; + property int posX:0; + property int posY:0; + property bool hasFocus : false; + property variant canvas; + property variant manager; + property variant linkColor; + property bool selected : false; + + Rectangle { + id:twitterStatus + x:twitterUser.width + y:twitterUser.height + width:250 + height:60 + opacity: 0 + border.color:"steelblue" + border.width:3 + Column { + spacing:2 + Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere} + Text {color:"steelblue"; font.pointSize:8; width:250; height:30; text:twitterUser.url; wrapMode: Text.WrapAnywhere} + } + } + + function moved() { + twitterUser.posX = twitterUser.x; + twitterUser.posY = twitterUser.y; + twitterUser.canvas.requestPaint(); + } + + onXChanged: moved(); + onYChanged: moved(); + + MouseArea { + anchors.fill:parent + drag.target : twitterUser + drag.axis : Drag.XandYAxis + + onClicked: { + if (!twitterUser.selected) { + twitterUser.selected = true; + twitterStatus.opacity = 1; + twitterStatus.visible = true; + } else { + twitterUser.selected = false; + twitterStatus.opacity = 0; + } + } + + onDoubleClicked : { + twitterStatus.opacity = 0; + twitterUser.selected = false; + twitterUser.hasFocus = true; + twitterUser.canvas.twitterName = twitterUser.name; + twitterUser.canvas.twitterId = twitterUser.twitterId; + twitterUser.canvas.loading = true; + twitterUser.createFriends(); + } + } + + function show(ctx, layoutChanged) { + var w = canvas.width; + var h = canvas.height; + if (twitterUser.hasFocus) { + twitterUser.width = 60 + twitterUser.height = 60 + twitterUser.posX = w/2; + twitterUser.posY = h/2; + } else { + twitterUser.width = 40 + twitterUser.height = 40 + } + + + if (twitterUser.hasFocus) { + if (layoutChanged) + twitterUser.layoutFriends(); + twitterUser.linkFriends(ctx); + twitterUser.showFriends(ctx); + ctx.shadowOffsetX = 5; + ctx.shadowOffsetY = 5; + ctx.shadowBlur = 7; + ctx.shadowColor = "blue"; + ctx.globalAlpha = 1; + } else { + ctx.shadowOffsetX = 5; + ctx.shadowOffsetY = 5; + ctx.shadowBlur = 7; + ctx.shadowColor = twitterUser.linkColor; + ctx.globalAlpha = 0.6; + } + + if (twitterUser.canvas.isImageLoaded(twitterUser.image)) { + ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height); + } +// ctx.font = "15px"; +// var nameSize = ctx.measureText(twitterUser.name).width; +// ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10); + } + function dump() { + console.log("name:" + twitterUser.name + + " x:" + twitterUser.posX + + " y:" + twitterUser.posY + + " width:" + twitterUser.width + + " height:" + twitterUser.height + + " id:" + twitterUser.twitterId + + " image:" + twitterUser.image + + " url:" + twitterUser.url + "\n" + twitterUser.desc); + } + + function layoutFriends() { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend) { + friend.x = Math.random() *w; + friend.y = Math.random() *h; + } + } + } + + function showFriends(ctx) { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length && i < 15; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { + friend.hasFocus = false; + friend.show(ctx, false); + } + } + } + + function linkFriends(ctx) { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length && i < 15; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { + if (!friend.linkColor) + friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255 + , ((Math.random() * 200) +55)/255 + , ((Math.random() * 200) +55)/255, 0.8); + ctx.strokeStyle = friend.linkColor; + ctx.lineWidth = 8; + ctx.beginPath(); + ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2); + ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2); + ctx.stroke(); + } + } + } + + + function create(url) { + var x = new XMLHttpRequest; + x.open("GET", url); + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + var user = eval('(' + x.responseText +')')[0]; + twitterUser.name = user.name; + twitterUser.twitterId = user.id; + twitterUser.image = user.profile_image_url; + twitterUser.canvas.loadImage(twitterUser.image); + twitterUser.url = user.url; + twitterUser.desc = user.description; + twitterUser.createFriends(); + } + } + x.send(); + } + + function createByName(name) { + if (twitterUser.name === "" && twitterUser.twitterId === "") { + twitterUser.name = name; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name; + twitterUser.create(userUrl); + } + } + + function createById(id) { + if (twitterUser.name === "" && twitterUser.twitterId === "") { + twitterUser.twitterId = id; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id; + twitterUser.create(userUrl); + } + } + + function createFriends() { + if (twitterUser.friends.length === 0) { + var x = new XMLHttpRequest; + var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId; + x.open("GET", friendsUrl); + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + twitterUser.friends = eval('(' + x.responseText +')').ids; + var doRequest = false; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id="; + + for (var i=0; i -#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/quick/canvas/stockchart/model.h b/examples/quick/canvas/stockchart/model.h deleted file mode 100644 index 95e6f48..0000000 --- a/examples/quick/canvas/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/quick/canvas/stockchart/plugin.cpp b/examples/quick/canvas/stockchart/plugin.cpp deleted file mode 100644 index 3b354e2..0000000 --- a/examples/quick/canvas/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/quick/canvas/stockchart/stock.qml b/examples/quick/canvas/stockchart/stock.qml deleted file mode 100644 index 1c95fde..0000000 --- a/examples/quick/canvas/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/quick/canvas/stockchart/stockchart.pro b/examples/quick/canvas/stockchart/stockchart.pro deleted file mode 100644 index e368746..0000000 --- a/examples/quick/canvas/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/quick/canvas/tiger/tiger.qml b/examples/quick/canvas/tiger/tiger.qml index 2eb1bb2..6b8e003 100644 --- a/examples/quick/canvas/tiger/tiger.qml +++ b/examples/quick/canvas/tiger/tiger.qml @@ -43,18 +43,18 @@ import "../contents" import "tiger.js" as Tiger Item { id:container - width:360 - height:600 + width:320 + height:480 Column { spacing:5 anchors.fill:parent - Text { font.pointSize:25; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter} + Text { font.pointSize:15; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter} Canvas { id:canvas - width:360 - height:360 + width:320 + height:280 smooth:true renderTarget:Canvas.FramebufferObject renderStrategy: Canvas.Cooperative @@ -115,14 +115,14 @@ Item { } Rectangle { id:controls - width:360 - height:160 + width:320 + height:150 Column { spacing:3 - Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleX"} - Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleY"} - Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} - Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} + Slider {id:scaleXCtrl; width:300; height:20; min:0.1; max:10; init:0.5; name:"ScaleX"} + Slider {id:scaleYCtrl; width:300; height:20; min:0.1; max:10; init:0.5; name:"ScaleY"} + Slider {id:rotateCtrl; width:300; height:20; min:0; max:Math.PI*2; init:0; name:"Rotate"} + Slider {id:alphaCtrl; width:300; height:20; min:0; max:1; init:1; name:"Alpha"} } } } diff --git a/examples/quick/canvas/twitterfriends/TwitterUser.qml b/examples/quick/canvas/twitterfriends/TwitterUser.qml deleted file mode 100644 index 8b90621..0000000 --- a/examples/quick/canvas/twitterfriends/TwitterUser.qml +++ /dev/null @@ -1,294 +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 - -Item { - id:twitterUser - property variant friends : []; - property string name : ""; - property string twitterId : ""; - property string image : ""; - property string url : ""; - property string desc : ""; - width : 0; - height : 0; - property int posX:0; - property int posY:0; - property bool hasFocus : false; - property variant canvas; - property variant manager; - property variant linkColor; - property bool selected : false; - - Rectangle { - id:twitterStatus - x:twitterUser.width - y:twitterUser.height - width:250 - height:60 - opacity: 0 - border.color:"steelblue" - border.width:3 - Column { - spacing:2 - Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere} - Text {color:"steelblue"; font.pointSize:8; width:250; height:30; text:twitterUser.url; wrapMode: Text.WrapAnywhere} - } - } - - function moved() { - twitterUser.posX = twitterUser.x; - twitterUser.posY = twitterUser.y; - twitterUser.canvas.requestPaint(); - } - - onXChanged: moved(); - onYChanged: moved(); - - MouseArea { - anchors.fill:parent - drag.target : twitterUser - drag.axis : Drag.XandYAxis - - onClicked: { - if (!twitterUser.selected) { - twitterUser.selected = true; - twitterStatus.opacity = 1; - twitterStatus.visible = true; - } else { - twitterUser.selected = false; - twitterStatus.opacity = 0; - } - } - - onDoubleClicked : { - twitterStatus.opacity = 0; - twitterUser.selected = false; - twitterUser.hasFocus = true; - twitterUser.canvas.twitterName = twitterUser.name; - twitterUser.canvas.twitterId = twitterUser.twitterId; - twitterUser.canvas.loading = true; - twitterUser.createFriends(); - } - } - - function show(ctx, layoutChanged) { - var w = canvas.width; - var h = canvas.height; - if (twitterUser.hasFocus) { - twitterUser.width = 60 - twitterUser.height = 60 - twitterUser.posX = w/2; - twitterUser.posY = h/2; - } else { - twitterUser.width = 40 - twitterUser.height = 40 - } - - - if (twitterUser.hasFocus) { - if (layoutChanged) - twitterUser.layoutFriends(); - twitterUser.linkFriends(ctx); - twitterUser.showFriends(ctx); - ctx.shadowOffsetX = 5; - ctx.shadowOffsetY = 5; - ctx.shadowBlur = 7; - ctx.shadowColor = "blue"; - ctx.globalAlpha = 1; - } else { - ctx.shadowOffsetX = 5; - ctx.shadowOffsetY = 5; - ctx.shadowBlur = 7; - ctx.shadowColor = twitterUser.linkColor; - ctx.globalAlpha = 0.6; - } - - if (twitterUser.canvas.isImageLoaded(twitterUser.image)) { - ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height); - } -// ctx.font = "15px"; -// var nameSize = ctx.measureText(twitterUser.name).width; -// ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10); - } - function dump() { - console.log("name:" + twitterUser.name - + " x:" + twitterUser.posX - + " y:" + twitterUser.posY - + " width:" + twitterUser.width - + " height:" + twitterUser.height - + " id:" + twitterUser.twitterId - + " image:" + twitterUser.image - + " url:" + twitterUser.url + "\n" + twitterUser.desc); - } - - function layoutFriends() { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend) { - friend.x = Math.random() *w; - friend.y = Math.random() *h; - } - } - } - - function showFriends(ctx) { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length && i < 15; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { - friend.hasFocus = false; - friend.show(ctx, false); - } - } - } - - function linkFriends(ctx) { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length && i < 15; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { - if (!friend.linkColor) - friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255 - , ((Math.random() * 200) +55)/255 - , ((Math.random() * 200) +55)/255, 0.8); - ctx.strokeStyle = friend.linkColor; - ctx.lineWidth = 8; - ctx.beginPath(); - ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2); - ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2); - ctx.stroke(); - } - } - } - - - function create(url) { - var x = new XMLHttpRequest; - x.open("GET", url); - - x.onreadystatechange = function() { - if (x.readyState == XMLHttpRequest.DONE) { - var user = eval('(' + x.responseText +')')[0]; - twitterUser.name = user.name; - twitterUser.twitterId = user.id; - twitterUser.image = user.profile_image_url; - twitterUser.canvas.loadImage(twitterUser.image); - twitterUser.url = user.url; - twitterUser.desc = user.description; - twitterUser.createFriends(); - } - } - x.send(); - } - - function createByName(name) { - if (twitterUser.name === "" && twitterUser.twitterId === "") { - twitterUser.name = name; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name; - twitterUser.create(userUrl); - } - } - - function createById(id) { - if (twitterUser.name === "" && twitterUser.twitterId === "") { - twitterUser.twitterId = id; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id; - twitterUser.create(userUrl); - } - } - - function createFriends() { - if (twitterUser.friends.length === 0) { - var x = new XMLHttpRequest; - var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId; - x.open("GET", friendsUrl); - - x.onreadystatechange = function() { - if (x.readyState == XMLHttpRequest.DONE) { - twitterUser.friends = eval('(' + x.responseText +')').ids; - var doRequest = false; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id="; - - for (var i=0; i