From 2b935e4f3207ac515ceed1fa653110df98ca7e4c 2012-05-07 10:31:31 From: Tero Ahola Date: 2012-05-07 10:31:31 Subject: [PATCH] Draft version for QML PieSeries model API --- diff --git a/demos/qmlchart/qml/qmlchart/View1.qml b/demos/qmlchart/qml/qmlchart/View1.qml index b76d5c1..0cfbda2 100644 --- a/demos/qmlchart/qml/qmlchart/View1.qml +++ b/demos/qmlchart/qml/qmlchart/View1.qml @@ -24,24 +24,88 @@ import QtCommercial.Chart 1.0 Rectangle { anchors.fill: parent - Chart { + ChartView { + id: chart title: "Car brand shares in Finland" - anchors.fill: parent - theme: Chart.ChartThemeLight - legend: Chart.LegendBottom + anchors.top: parent.top + anchors.bottom: button.top + anchors.left: parent.left + anchors.right: parent.right + theme: ChartView.ChartThemeLight + legend: ChartView.LegendBottom + animationOptions: ChartView.SeriesAnimations PieSeries { - horizontalPosition: 0.5 - verticalPosition: 0.5 - size: 0.7 - slices: [ - PieSlice { label: "Volkswagen"; value: 13.5 }, - PieSlice { label: "Toyota"; value: 10.9 }, - PieSlice { label: "Ford"; value: 8.6 }, - PieSlice { label: "Skoda"; value: 8.2 }, - PieSlice { label: "Volvo"; value: 6.8 }, - PieSlice { label: "Others"; value: 52.0 } - ] + model: PieModel { + id: pieModel + PieSlice { label: "Volkswagen"; value: 13.5 } + PieSlice { label: "Toyota"; value: 10.9 } + PieSlice { label: "Ford"; value: 8.6 } + PieSlice { label: "Skoda"; value: 8.2 } + PieSlice { label: "Volvo"; value: 6.8 } + } } } + + Rectangle { + id: button + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + height: 40 + width: 100 + color: "orange" + radius: 5 + Text { + id: buttonText + anchors.centerIn: parent + text: button.state == "" ? "Show others" : "Hide others" + } + MouseArea { + anchors.fill: parent + onClicked: { + if (button.state == "") { + // The share of "others" was enabled -> append the data into the model + // TODO: this should also be doable by redefining the range inside the model + button.state = "show"; + pieModel.append(["Others", 52.0]); + } else { + // The share of "others" was disabled -> remove the data from the model + // TODO: this should also be doable by redefining the range inside the model + button.state = ""; + pieModel.removeRow(pieModel.count - 1); + } + } + } + } + + + // TODO: Optional syntax for defining models for different series. Is this really needed? +// ChartModel { +// id: chartModel +// ChartElement { column1: "Volkswagen"; column2: 13.5; column3: 1.2 } +// ChartElement { column1: "Toyota"; column2: 10.9; column3: 2.5 } +// } +// // column3 not used by pie series +// PieSeries { +// model: chartModel +// mappings: [ {"column1":"label"}, {"column2":"value"} ] +// } + + + // TODO: show how to use data from a list model in a chart view + // i.e. copy the data into a chart model +// ListModel { +// id: listModel +// ListElement { +// label: "Volkswagen" +// value: 13.5 +// } +// ListElement { +// label: "Toyota" +// value: 10.9 +// } +// // and so on... +// } + } diff --git a/demos/qmlchart/qml/qmlchart/View2.qml b/demos/qmlchart/qml/qmlchart/View2.qml index a0f750a..379710b 100644 --- a/demos/qmlchart/qml/qmlchart/View2.qml +++ b/demos/qmlchart/qml/qmlchart/View2.qml @@ -24,11 +24,11 @@ import QtCommercial.Chart 1.0 Rectangle { anchors.fill: parent - Chart { + ChartView { title: "Line&Spline" anchors.fill: parent - theme: Chart.ChartThemeBrownSand - animationOptions: Chart.NoAnimation + theme: ChartView.ChartThemeBrownSand + animationOptions: ChartView.NoAnimation LineSeries { name: "Line" diff --git a/demos/qmlchart/qml/qmlchart/View3.qml b/demos/qmlchart/qml/qmlchart/View3.qml index 97e2cf3..c1a2b9c 100644 --- a/demos/qmlchart/qml/qmlchart/View3.qml +++ b/demos/qmlchart/qml/qmlchart/View3.qml @@ -24,11 +24,11 @@ import QtCommercial.Chart 1.0 Rectangle { anchors.fill: parent - Chart { + ChartView { title: "NHL All-Star Team Players" anchors.fill: parent - theme: Chart.ChartThemeHighContrast - legend: Chart.LegendTop + theme: ChartView.ChartThemeHighContrast + legend: ChartView.LegendTop AreaSeries { name: "Swedish" diff --git a/demos/qmlchart/qml/qmlchart/View4.qml b/demos/qmlchart/qml/qmlchart/View4.qml index f1d297a..bfac53b 100644 --- a/demos/qmlchart/qml/qmlchart/View4.qml +++ b/demos/qmlchart/qml/qmlchart/View4.qml @@ -24,10 +24,10 @@ import QtCommercial.Chart 1.0 Rectangle { anchors.fill: parent - Chart { + ChartView { title: "Scatters" anchors.fill: parent - theme: Chart.ChartThemeBlueCerulean + theme: ChartView.ChartThemeBlueCerulean ScatterSeries { id: scatter1 diff --git a/demos/qmlchart/qml/qmlchart/View5.qml b/demos/qmlchart/qml/qmlchart/View5.qml index 5c3f9ad..f388093 100644 --- a/demos/qmlchart/qml/qmlchart/View5.qml +++ b/demos/qmlchart/qml/qmlchart/View5.qml @@ -24,11 +24,11 @@ import QtCommercial.Chart 1.0 Rectangle { anchors.fill: parent - Chart { + ChartView { title: "Bar series" anchors.fill: parent - theme: Chart.ChartThemeLight - legend: Chart.LegendBottom + theme: ChartView.ChartThemeLight + legend: ChartView.LegendBottom BarSeries { barCategories: [ "2008", "2009", "2010", "2011", "2012" ] diff --git a/demos/qmlchart/qml/qmlchart/main.qml b/demos/qmlchart/qml/qmlchart/main.qml index fe4efbe..01b35fd 100644 --- a/demos/qmlchart/qml/qmlchart/main.qml +++ b/demos/qmlchart/qml/qmlchart/main.qml @@ -26,13 +26,9 @@ Rectangle { height: parent.height property int __viewNumber: 0 - Timer { - id: timer - running: true - repeat: true - interval: 5000 - triggeredOnStart: false - onTriggered: { + MouseArea { + anchors.fill: parent + onClicked: { __viewNumber++; } } @@ -42,12 +38,4 @@ Rectangle { anchors.fill: parent source: "View" + (__viewNumber % 5 + 1) + ".qml"; } - - MouseArea { - anchors.fill: parent - onClicked: { - timer.restart(); - __viewNumber++; - } - } } diff --git a/qmlplugin/declarativepiemodel.cpp b/qmlplugin/declarativepiemodel.cpp new file mode 100644 index 0000000..454d576 --- /dev/null +++ b/qmlplugin/declarativepiemodel.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "DeclarativePieModel.h" +#include "declarativechart.h" +#include "qchart.h" +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +DeclarativePieModel::DeclarativePieModel(QObject *parent) : + ChartTableModel(parent) +{ +} + +//void DeclarativePieModel::classBegin() +//{ +//} + +//void DeclarativePieModel::componentComplete() +//{ +//} + +void DeclarativePieModel::append(QPieSlice* slice) +{ + // TODO: label not working... + qDebug() << "DeclarativePieModel::append:" << slice->label() << " " << slice->value(); + qDebug() << "rowCount:" << rowCount(); + qDebug() << "coolCount:" << columnCount(); + insertRow(rowCount()); + qDebug() << "new rowCount:" << rowCount(); + + qDebug() << setData(createIndex(rowCount() - 1, 0), slice->value()); + qDebug() << setData(createIndex(rowCount() - 1, 1), slice->label()); +} + +void DeclarativePieModel::append(QVariantList slices) +{ + qDebug() << "append:" << slices; + QString label = ""; + for (int i(0); i < slices.count(); i++) { + if (i % 2) { + bool ok(false); + qreal value = slices.at(i).toReal(&ok); + if (ok) { + QPieSlice *slice = new QPieSlice(value, label); + append(slice); + } + } else { + label = slices.at(i).toString(); + } + } +} + +QDeclarativeListProperty DeclarativePieModel::slices() +{ + return QDeclarativeListProperty(this, 0, &DeclarativePieModel::appendSlice); +} + +void DeclarativePieModel::appendSlice(QDeclarativeListProperty *list, + QPieSlice *slice) +{ + DeclarativePieModel *pieModel = qobject_cast(list->object); + if (pieModel) + pieModel->append(slice); + else + qWarning() << "Illegal slice item"; +} + +#include "moc_declarativepiemodel.cpp" + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/qmlplugin/declarativepiemodel.h b/qmlplugin/declarativepiemodel.h new file mode 100644 index 0000000..fb56a86 --- /dev/null +++ b/qmlplugin/declarativepiemodel.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DECLARATIVEPIEMODEL_H +#define DECLARATIVEPIEMODEL_H + +#include "qchartglobal.h" +#include "qpieslice.h" +#include "qpieseries.h" +#include "../src/charttablemodel.h" +#include +#include +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class DeclarativePieModel : public ChartTableModel/*, public QDeclarativeParserStatus*/ +{ +// Q_INTERFACES(QDeclarativeParserStatus) + Q_OBJECT + Q_PROPERTY(QDeclarativeListProperty slices READ slices) + Q_CLASSINFO("DefaultProperty", "slices") + +public: + explicit DeclarativePieModel(QObject *parent = 0); + QDeclarativeListProperty slices(); + +//public: // from QDeclarativeParserStatus +// virtual void classBegin(); +// virtual void componentComplete(); + +public Q_SLOTS: + void append(QPieSlice* slice); + void append(QVariantList slices); + static void appendSlice(QDeclarativeListProperty *list, + QPieSlice *element); + +public: +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // DECLARATIVEPIEMODEL_H diff --git a/qmlplugin/declarativepieseries.cpp b/qmlplugin/declarativepieseries.cpp index f5f31bf..74f0af4 100644 --- a/qmlplugin/declarativepieseries.cpp +++ b/qmlplugin/declarativepieseries.cpp @@ -21,6 +21,7 @@ #include "declarativepieseries.h" #include "declarativechart.h" #include "qchart.h" +#include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -29,17 +30,20 @@ DeclarativePieSeries::DeclarativePieSeries(QObject *parent) : { } -QDeclarativeListProperty DeclarativePieSeries::slices() +bool DeclarativePieSeries::setPieModel(DeclarativePieModel *model) { - return QDeclarativeListProperty(this, 0, &DeclarativePieSeries::appendSlice); + QAbstractItemModel *m = qobject_cast(model); + bool value(false); + if (m) { + value = QPieSeries::setModel(m); + setModelMapping(0, 1, Qt::Vertical); + } + return value; } -void DeclarativePieSeries::appendSlice(QDeclarativeListProperty *list, - QPieSlice *slice) +DeclarativePieModel *DeclarativePieSeries::pieModel() { - DeclarativePieSeries *series = qobject_cast(list->object); - if (series) - series->append(slice->value(), slice->label()); + return qobject_cast(model()); } #include "moc_declarativepieseries.cpp" diff --git a/qmlplugin/declarativepieseries.h b/qmlplugin/declarativepieseries.h index bc13132..01ed03a 100644 --- a/qmlplugin/declarativepieseries.h +++ b/qmlplugin/declarativepieseries.h @@ -25,6 +25,9 @@ #include "qpieslice.h" #include "qpieseries.h" #include +#include +#include +#include "declarativepiemodel.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -33,15 +36,16 @@ class QChart; class DeclarativePieSeries : public QPieSeries { Q_OBJECT - Q_PROPERTY(QDeclarativeListProperty slices READ slices) + Q_PROPERTY(DeclarativePieModel *model READ pieModel WRITE setPieModel) public: explicit DeclarativePieSeries(QObject *parent = 0); - QDeclarativeListProperty slices(); public Q_SLOTS: - static void appendSlice(QDeclarativeListProperty *list, - QPieSlice *element); + +public: + bool setPieModel(DeclarativePieModel *model); + DeclarativePieModel *pieModel(); }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/qmlplugin/plugin.cpp b/qmlplugin/plugin.cpp index dc01730..11f3dbc 100644 --- a/qmlplugin/plugin.cpp +++ b/qmlplugin/plugin.cpp @@ -30,6 +30,7 @@ #include "declarativescatterseries.h" #include "declarativebarseries.h" #include "declarativepieseries.h" +#include "declarativepiemodel.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -41,7 +42,7 @@ public: { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtCommercial.Chart")); - qmlRegisterType(uri, 1, 0, "Chart"); + qmlRegisterType(uri, 1, 0, "ChartView"); qmlRegisterType(uri, 1, 0, "Axis"); qmlRegisterType(uri, 1, 0, "XyPoint"); qmlRegisterType(uri, 1, 0, "ScatterSeries"); @@ -51,6 +52,8 @@ public: qmlRegisterType(uri, 1, 0, "BarSeries"); qmlRegisterType(uri, 1, 0, "PieSeries"); qmlRegisterType(uri, 1, 0, "PieSlice"); + // TODO: a declarative model for each type + qmlRegisterType(uri, 1, 0, "PieModel"); } }; diff --git a/qmlplugin/qmlplugin.pro b/qmlplugin/qmlplugin.pro index 20264a5..6df9f78 100644 --- a/qmlplugin/qmlplugin.pro +++ b/qmlplugin/qmlplugin.pro @@ -29,7 +29,8 @@ SOURCES += \ declarativeareaseries.cpp \ declarativescatterseries.cpp \ declarativepieseries.cpp \ - declarativebarseries.cpp + declarativebarseries.cpp \ + declarativepiemodel.cpp HEADERS += \ declarativechart.h \ declarativeaxis.h \ @@ -40,7 +41,8 @@ HEADERS += \ declarativeareaseries.h \ declarativescatterseries.h \ declarativepieseries.h \ - declarativebarseries.h + declarativebarseries.h \ + declarativepiemodel.h TARGETPATH = QtCommercial/Chart target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH diff --git a/src/charttablemodel.cpp b/src/charttablemodel.cpp new file mode 100644 index 0000000..e99d18b --- /dev/null +++ b/src/charttablemodel.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "charttablemodel.h" +#include +#include +#include +#include + +QTCOMMERCIALCHART_USE_NAMESPACE + +ChartTableModel::ChartTableModel(QObject *parent) : + QAbstractTableModel(parent) +{ + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + + m_columnCount = 2; + m_rowCount = 0; + + // m_data + for (int i = 0; i < m_rowCount; i++) { + QVector* dataVec = new QVector(m_columnCount); + for (int k = 0; k < dataVec->size(); k++) { + if (k%2 == 0) + dataVec->replace(k, i * 50 + qrand()%20); + else + dataVec->replace(k, qrand()%100); + } + m_data.append(dataVec); + } +} + +int ChartTableModel::rowCount(const QModelIndex & parent) const +{ + Q_UNUSED(parent) + return m_data.count(); +} + +int ChartTableModel::columnCount(const QModelIndex & parent) const +{ + Q_UNUSED(parent) + return m_columnCount; +} + +QVariant ChartTableModel::headerData (int section, Qt::Orientation orientation, int role ) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + if (section%2 == 0) + return "x"; + else + return "y"; + } + else + return QString("%1").arg(section + 1); +} + +QVariant ChartTableModel::data(const QModelIndex &index, int role) const +{ + if (role == Qt::DisplayRole) { + return m_data[index.row()]->at(index.column()); + } else if (role == Qt::EditRole) { + return m_data[index.row()]->at(index.column()); + } + return QVariant(); +} + +bool ChartTableModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (index.isValid() && role == Qt::EditRole) { + m_data[index.row()]->replace(index.column(), value); + emit dataChanged(index, index); + return true; + } + return false; +} + +void ChartTableModel::insertRow(int row, const QModelIndex &parent) +{ + Q_UNUSED(parent) + + beginInsertRows(QModelIndex(), row, row); + QVector* dataVec = new QVector(m_columnCount); + m_data.insert(row, dataVec); + endInsertRows(); +} + +//bool ChartTableModel::removeRow(int row, const QModelIndex &parent) +//{ +// Q_UNUSED(parent) +// Q_ASSERT(row >= 0 && row < rowCount); + +// beginRemoveRows(parent, row, row); +// m_data.removeAt(row); +// endRemoveRows(); +// return true; +//} + +bool ChartTableModel::removeRow(int row, const QModelIndex &parent) +{ + return QAbstractTableModel::removeRow(row, parent); +} + +bool ChartTableModel::removeRows(int row, int count, const QModelIndex &parent) +{ + beginRemoveRows(parent, row, row + count - 1); + bool removed(false); + for (int i(row); i < (row + count); i++) { + m_data.removeAt(i); + removed = true; + } + endRemoveRows(); + return removed; +} + +Qt::ItemFlags ChartTableModel::flags ( const QModelIndex & index ) const +{ + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +} + +#include "moc_charttablemodel.cpp" diff --git a/src/charttablemodel.h b/src/charttablemodel.h new file mode 100644 index 0000000..e13cd80 --- /dev/null +++ b/src/charttablemodel.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHARTTABLEMODEL_H +#define CHARTTABLEMODEL_H + +#include "qchartglobal.h" +#include +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QTCOMMERCIALCHART_EXPORT ChartTableModel : public QAbstractTableModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount) + +public: + explicit ChartTableModel(QObject *parent = 0); + + int rowCount ( const QModelIndex & parent = QModelIndex() ) const; + int columnCount ( const QModelIndex & parent = QModelIndex() ) const; + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); + Qt::ItemFlags flags ( const QModelIndex & index ) const; + void insertRow(int row, const QModelIndex &parent = QModelIndex()); + /*Q_INVOKABLE*/ //bool removeRow(int row, const QModelIndex &parent = QModelIndex()); + Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex()); + Q_INVOKABLE bool removeRow (int row, const QModelIndex &parent = QModelIndex()); + +private: + QList * > m_data; + int m_columnCount; + int m_rowCount; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // CHARTTABLEMODEL_H diff --git a/src/src.pro b/src/src.pro index 5dfd961..8e216f6 100644 --- a/src/src.pro +++ b/src/src.pro @@ -37,7 +37,8 @@ SOURCES += \ $$PWD/qabstractseries.cpp \ $$PWD/chartbackground.cpp \ $$PWD/chart.cpp \ - $$PWD/scroller.cpp + $$PWD/scroller.cpp \ + $$PWD/charttablemodel.cpp PRIVATE_HEADERS += \ $$PWD/chartdataset_p.h \ $$PWD/chartitem_p.h \ @@ -50,7 +51,8 @@ PRIVATE_HEADERS += \ $$PWD/qchart_p.h \ $$PWD/qchartview_p.h \ $$PWD/scroller_p.h \ - $$PWD/qabstractseries_p.h + $$PWD/qabstractseries_p.h \ + $$PWD/charttablemodel.h PUBLIC_HEADERS += \ $$PWD/qchart.h \ $$PWD/qchartglobal.h \