diff options
-rw-r--r-- | src/datavisualization/data/baritemmodelhandler.cpp | 50 | ||||
-rw-r--r-- | src/datavisualization/data/baritemmodelhandler_p.h | 6 | ||||
-rw-r--r-- | src/datavisualization/data/scatteritemmodelhandler.cpp | 6 | ||||
-rw-r--r-- | src/datavisualization/data/surfaceitemmodelhandler.cpp | 78 | ||||
-rw-r--r-- | src/datavisualization/data/surfaceitemmodelhandler_p.h | 7 | ||||
-rw-r--r-- | src/datavisualization/engine/bars3dcontroller.cpp | 6 | ||||
-rw-r--r-- | src/datavisualization/engine/bars3drenderer.cpp | 13 | ||||
-rw-r--r-- | tests/itemmodeltest/itemmodeltest.pro | 11 | ||||
-rw-r--r-- | tests/itemmodeltest/main.cpp | 293 | ||||
-rw-r--r-- | tests/tests.pro | 3 |
10 files changed, 439 insertions, 34 deletions
diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp index 4f44fe1d..3b02c1e3 100644 --- a/src/datavisualization/data/baritemmodelhandler.cpp +++ b/src/datavisualization/data/baritemmodelhandler.cpp @@ -26,7 +26,9 @@ BarItemModelHandler::BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject : AbstractItemModelHandler(parent), m_proxy(proxy), m_proxyArray(0), - m_columnCount(0) + m_columnCount(0), + m_valueRole(noRoleIndex), + m_rotationRole(noRoleIndex) { } @@ -34,6 +36,34 @@ BarItemModelHandler::~BarItemModelHandler() { } +void BarItemModelHandler::handleDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector<int> &roles) +{ + // Do nothing if full reset already pending + if (!m_fullReset) { + if (!m_proxy->useModelCategories()) { + // If the data model doesn't directly map rows and columns, we cannot optimize + AbstractItemModelHandler::handleDataChanged(topLeft, bottomRight, roles); + } else { + int startRow = qMin(topLeft.row(), bottomRight.row()); + int endRow = qMax(topLeft.row(), bottomRight.row()); + int startCol = qMin(topLeft.column(), bottomRight.column()); + int endCol = qMax(topLeft.column(), bottomRight.column()); + + for (int i = startRow; i <= endRow; i++) { + for (int j = startCol; j <= endCol; j++) { + QBarDataItem item; + item.setValue(m_itemModel->index(i, j).data(m_valueRole).toFloat()); + if (m_rotationRole != noRoleIndex) + item.setRotation(m_itemModel->index(i, j).data(m_rotationRole).toFloat()); + m_proxy->setItem(i, j, item); + } + } + } + } +} + // Resolve entire item model into QBarDataArray. void BarItemModelHandler::resolveModel() { @@ -54,8 +84,8 @@ void BarItemModelHandler::resolveModel() QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); // Default value role to display role if no mapping - int valueRole = roleHash.key(m_proxy->valueRole().toLatin1(), Qt::DisplayRole); - int rotationRole = roleHash.key(m_proxy->rotationRole().toLatin1(), noRoleIndex); + m_valueRole = roleHash.key(m_proxy->valueRole().toLatin1(), Qt::DisplayRole); + m_rotationRole = roleHash.key(m_proxy->rotationRole().toLatin1(), noRoleIndex); int rowCount = m_itemModel->rowCount(); int columnCount = m_itemModel->columnCount(); @@ -71,9 +101,9 @@ void BarItemModelHandler::resolveModel() for (int i = 0; i < rowCount; i++) { QBarDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnCount; j++) { - newProxyRow[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal()); - if (rotationRole != noRoleIndex) - newProxyRow[j].setRotation(m_itemModel->index(i, j).data(rotationRole).toReal()); + newProxyRow[j].setValue(m_itemModel->index(i, j).data(m_valueRole).toFloat()); + if (m_rotationRole != noRoleIndex) + newProxyRow[j].setRotation(m_itemModel->index(i, j).data(m_rotationRole).toFloat()); } } // Generate labels from headers if using model rows/columns @@ -104,9 +134,9 @@ void BarItemModelHandler::resolveModel() QModelIndex index = m_itemModel->index(i, j); QString rowRoleStr = index.data(rowRole).toString(); QString columnRoleStr = index.data(columnRole).toString(); - itemValueMap[rowRoleStr][columnRoleStr] = index.data(valueRole).toReal(); - if (rotationRole != noRoleIndex) - itemRotationMap[rowRoleStr][columnRoleStr] = index.data(rotationRole).toReal(); + itemValueMap[rowRoleStr][columnRoleStr] = index.data(m_valueRole).toFloat(); + if (m_rotationRole != noRoleIndex) + itemRotationMap[rowRoleStr][columnRoleStr] = index.data(m_rotationRole).toFloat(); if (generateRows && !rowListHash.value(rowRoleStr, false)) { rowListHash.insert(rowRoleStr, true); rowList << rowRoleStr; @@ -142,7 +172,7 @@ void BarItemModelHandler::resolveModel() QBarDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnList.size(); j++) { newProxyRow[j].setValue(itemValueMap[rowKey][columnList.at(j)]); - if (rotationRole != noRoleIndex) + if (m_rotationRole != noRoleIndex) newProxyRow[j].setRotation(itemRotationMap[rowKey][columnList.at(j)]); } } diff --git a/src/datavisualization/data/baritemmodelhandler_p.h b/src/datavisualization/data/baritemmodelhandler_p.h index 7bf7b0a1..737e0055 100644 --- a/src/datavisualization/data/baritemmodelhandler_p.h +++ b/src/datavisualization/data/baritemmodelhandler_p.h @@ -41,12 +41,18 @@ public: BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject *parent = 0); virtual ~BarItemModelHandler(); +public slots: + virtual void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles = QVector<int> ()); + protected: void virtual resolveModel(); QItemModelBarDataProxy *m_proxy; // Not owned QBarDataArray *m_proxyArray; // Not owned int m_columnCount; + int m_valueRole; + int m_rotationRole; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/scatteritemmodelhandler.cpp b/src/datavisualization/data/scatteritemmodelhandler.cpp index 08ed12f3..280f2a23 100644 --- a/src/datavisualization/data/scatteritemmodelhandler.cpp +++ b/src/datavisualization/data/scatteritemmodelhandler.cpp @@ -25,7 +25,11 @@ static const int noRoleIndex = -1; ScatterItemModelHandler::ScatterItemModelHandler(QItemModelScatterDataProxy *proxy, QObject *parent) : AbstractItemModelHandler(parent), m_proxy(proxy), - m_proxyArray(0) + m_proxyArray(0), + m_xPosRole(noRoleIndex), + m_yPosRole(noRoleIndex), + m_zPosRole(noRoleIndex), + m_rotationRole(noRoleIndex) { } diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp index f4383dbf..584ddf28 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler.cpp +++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp @@ -25,7 +25,10 @@ static const int noRoleIndex = -1; SurfaceItemModelHandler::SurfaceItemModelHandler(QItemModelSurfaceDataProxy *proxy, QObject *parent) : AbstractItemModelHandler(parent), m_proxy(proxy), - m_proxyArray(0) + m_proxyArray(0), + m_xPosRole(noRoleIndex), + m_yPosRole(noRoleIndex), + m_zPosRole(noRoleIndex) { } @@ -33,6 +36,45 @@ SurfaceItemModelHandler::~SurfaceItemModelHandler() { } +void SurfaceItemModelHandler::handleDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector<int> &roles) +{ + // Do nothing if full reset already pending + if (!m_fullReset) { + if (!m_proxy->useModelCategories()) { + // If the data model doesn't directly map rows and columns, we cannot optimize + AbstractItemModelHandler::handleDataChanged(topLeft, bottomRight, roles); + } else { + int startRow = qMin(topLeft.row(), bottomRight.row()); + int endRow = qMax(topLeft.row(), bottomRight.row()); + int startCol = qMin(topLeft.column(), bottomRight.column()); + int endCol = qMax(topLeft.column(), bottomRight.column()); + + for (int i = startRow; i <= endRow; i++) { + for (int j = startCol; j <= endCol; j++) { + QSurfaceDataItem item; + const QSurfaceDataItem *oldItem = m_proxy->itemAt(i, j); + float xPos; + float zPos; + if (m_xPosRole != noRoleIndex) + xPos = m_itemModel->index(i, j).data(m_xPosRole).toFloat(); + else + xPos = oldItem->x(); + if (m_zPosRole != noRoleIndex) + zPos = m_itemModel->index(i, j).data(m_zPosRole).toFloat(); + else + zPos = oldItem->z(); + item.setPosition(QVector3D(xPos, + m_itemModel->index(i, j).data(m_yPosRole).toFloat(), + zPos)); + m_proxy->setItem(i, j, item); + } + } + } + } +} + // Resolve entire item model into QSurfaceDataArray. void SurfaceItemModelHandler::resolveModel() { @@ -52,9 +94,9 @@ void SurfaceItemModelHandler::resolveModel() QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); // Default to display role if no mapping - int xPosRole = roleHash.key(m_proxy->xPosRole().toLatin1(), noRoleIndex); - int yPosRole = roleHash.key(m_proxy->yPosRole().toLatin1(), Qt::DisplayRole); - int zPosRole = roleHash.key(m_proxy->zPosRole().toLatin1(), noRoleIndex); + m_xPosRole = roleHash.key(m_proxy->xPosRole().toLatin1(), noRoleIndex); + m_yPosRole = roleHash.key(m_proxy->yPosRole().toLatin1(), Qt::DisplayRole); + m_zPosRole = roleHash.key(m_proxy->zPosRole().toLatin1(), noRoleIndex); int rowCount = m_itemModel->rowCount(); int columnCount = m_itemModel->columnCount(); @@ -70,10 +112,10 @@ void SurfaceItemModelHandler::resolveModel() for (int i = 0; i < rowCount; i++) { QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnCount; j++) { - float xPos = j; - float zPos = i; - if (xPosRole != noRoleIndex) { - xPos = m_itemModel->index(i, j).data(xPosRole).toFloat(); + float xPos = float(j); + float zPos = float(i); + if (m_xPosRole != noRoleIndex) { + xPos = m_itemModel->index(i, j).data(m_xPosRole).toFloat(); } else { QString header = m_itemModel->headerData(j, Qt::Horizontal).toString(); bool ok = false; @@ -82,8 +124,8 @@ void SurfaceItemModelHandler::resolveModel() xPos = headerValue; } - if (zPosRole != noRoleIndex) { - zPos = m_itemModel->index(i, j).data(zPosRole).toFloat(); + if (m_zPosRole != noRoleIndex) { + zPos = m_itemModel->index(i, j).data(m_zPosRole).toFloat(); } else { QString header = m_itemModel->headerData(i, Qt::Vertical).toString(); bool ok = false; @@ -94,17 +136,17 @@ void SurfaceItemModelHandler::resolveModel() newProxyRow[j].setPosition( QVector3D(xPos, - m_itemModel->index(i, j).data(yPosRole).toFloat(), + m_itemModel->index(i, j).data(m_yPosRole).toFloat(), zPos)); } } } else { int rowRole = roleHash.key(m_proxy->rowRole().toLatin1()); int columnRole = roleHash.key(m_proxy->columnRole().toLatin1()); - if (xPosRole == noRoleIndex) - xPosRole = columnRole; - if (zPosRole == noRoleIndex) - zPosRole = rowRole; + if (m_xPosRole == noRoleIndex) + m_xPosRole = columnRole; + if (m_zPosRole == noRoleIndex) + m_zPosRole = rowRole; bool generateRows = m_proxy->autoRowCategories(); bool generateColumns = m_proxy->autoColumnCategories(); @@ -124,9 +166,9 @@ void SurfaceItemModelHandler::resolveModel() QModelIndex index = m_itemModel->index(i, j); QString rowRoleStr = index.data(rowRole).toString(); QString columnRoleStr = index.data(columnRole).toString(); - QVector3D itemPos(index.data(xPosRole).toReal(), - index.data(yPosRole).toReal(), - index.data(zPosRole).toReal()); + QVector3D itemPos(index.data(m_xPosRole).toFloat(), + index.data(m_yPosRole).toFloat(), + index.data(m_zPosRole).toFloat()); itemValueMap[rowRoleStr][columnRoleStr] = itemPos; if (generateRows && !rowListHash.value(rowRoleStr, false)) { rowListHash.insert(rowRoleStr, true); diff --git a/src/datavisualization/data/surfaceitemmodelhandler_p.h b/src/datavisualization/data/surfaceitemmodelhandler_p.h index ae426433..dbed0a60 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler_p.h +++ b/src/datavisualization/data/surfaceitemmodelhandler_p.h @@ -41,11 +41,18 @@ public: SurfaceItemModelHandler(QItemModelSurfaceDataProxy *proxy, QObject *parent = 0); virtual ~SurfaceItemModelHandler(); +public slots: + virtual void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles = QVector<int> ()); + protected: void virtual resolveModel(); QItemModelSurfaceDataProxy *m_proxy; // Not owned QSurfaceDataArray *m_proxyArray; // Not owned + int m_xPosRole; + int m_yPosRole; + int m_zPosRole; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 99fa8223..35b24218 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -148,7 +148,6 @@ void Bars3DController::handleRowsChanged(int startIndex, int count) if (!oldChangeCount) m_changedRows.reserve(count); - int selectedRow = m_selectedBar.x(); for (int i = 0; i < count; i++) { bool newItem = true; int candidate = startIndex + i; @@ -162,7 +161,7 @@ void Bars3DController::handleRowsChanged(int startIndex, int count) if (newItem) { ChangeRow newChangeItem = {series, candidate}; m_changedRows.append(newChangeItem); - if (series == m_selectedBarSeries && selectedRow == candidate) + if (series == m_selectedBarSeries && m_selectedBar.x() == candidate) series->d_ptr->markItemLabelDirty(); } } @@ -516,7 +515,8 @@ void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *seri adjustSelectionPosition(pos, series); if (selectionMode().testFlag(QAbstract3DGraph::SelectionSlice)) { - // If the selected bar is outside data window, or there is no visible selected bar, disable slicing + // If the selected bar is outside data window, or there is no visible selected bar, + // disable slicing. if (pos.x() < m_axisZ->min() || pos.x() > m_axisZ->max() || pos.y() < m_axisX->min() || pos.y() > m_axisX->max() || !series->isVisible()) { diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index ab7bb4ca..f93d20b6 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -337,8 +337,14 @@ void Bars3DRenderer::updateRows(const QVector<Bars3DController::ChangeRow> &rows if (!cache->isVisible() && !cache->dataDirty()) cache->setDataDirty(true); } - if (cache->isVisible()) + if (cache->isVisible()) { updateRenderRow(dataArray->at(row), cache->renderArray()[row - minRow]); + if (m_cachedIsSlicingActivated + && cache == m_selectedSeriesCache + && m_selectedBarPos.x() == row) { + m_selectionDirty = true; // Need to update slice view + } + } } } @@ -370,6 +376,11 @@ void Bars3DRenderer::updateItems(const QVector<Bars3DController::ChangeItem> &it if (cache->isVisible()) { updateRenderItem(dataArray->at(row)->at(col), cache->renderArray()[row - minRow][col - minCol]); + if (m_cachedIsSlicingActivated + && cache == m_selectedSeriesCache + && m_selectedBarPos == QPoint(row, col)) { + m_selectionDirty = true; // Need to update slice view + } } } } diff --git a/tests/itemmodeltest/itemmodeltest.pro b/tests/itemmodeltest/itemmodeltest.pro new file mode 100644 index 00000000..d1cf0959 --- /dev/null +++ b/tests/itemmodeltest/itemmodeltest.pro @@ -0,0 +1,11 @@ +android|ios { + error( "This test is not supported for android or ios." ) +} + +!include( ../tests.pri ) { + error( "Couldn't find the tests.pri file!" ) +} + +SOURCES += main.cpp + +QT += widgets diff --git a/tests/itemmodeltest/main.cpp b/tests/itemmodeltest/main.cpp new file mode 100644 index 00000000..419ee162 --- /dev/null +++ b/tests/itemmodeltest/main.cpp @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise 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 +** +****************************************************************************/ + +#include <QtDataVisualization/q3dbars.h> +#include <QtDataVisualization/q3dsurface.h> +#include <QtDataVisualization/qcategory3daxis.h> +#include <QtDataVisualization/qitemmodelbardataproxy.h> +#include <QtDataVisualization/qitemmodelsurfacedataproxy.h> +#include <QtDataVisualization/qvalue3daxis.h> +#include <QtDataVisualization/q3dscene.h> +#include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> +#include <QtDataVisualization/q3dtheme.h> + +#include <QtWidgets/QApplication> +#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/QTableWidget> +#include <QtGui/QScreen> +#include <QtCore/QTimer> +#include <QtCore/QDebug> +#include <QtWidgets/QHeaderView> +#include <QtWidgets/QPushButton> + +#define USE_STATIC_DATA + +using namespace QtDataVisualization; + +class GraphDataGenerator : public QObject +{ +public: + explicit GraphDataGenerator(Q3DBars *bargraph, Q3DSurface * surfaceGraph, + QTableWidget *tableWidget); + ~GraphDataGenerator(); + + void setupModel(); + void addRow(); + void changeStyle(); + void changePresetCamera(); + void changeTheme(); + void start(); + void selectFromTable(const QPoint &selection); + void selectedFromTable(int currentRow, int currentColumn, int previousRow, int previousColumn); + void fixTableSize(); + void changeSelectedButtonClicked(); + +private: + Q3DBars *m_barGraph; + Q3DSurface *m_surfaceGraph; + QTimer *m_dataTimer; + QTimer *m_styleTimer; + QTimer *m_presetTimer; + QTimer *m_themeTimer; + int m_columnCount; + int m_rowCount; + QTableWidget *m_tableWidget; // not owned +}; + +GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, Q3DSurface * surfaceGraph, + QTableWidget *tableWidget) + : m_barGraph(bargraph), + m_surfaceGraph(surfaceGraph), + m_dataTimer(0), + m_styleTimer(0), + m_presetTimer(0), + m_themeTimer(0), + m_columnCount(100), + m_rowCount(50), + m_tableWidget(tableWidget) +{ + // Set up bar specifications; make the bars as wide as they are deep, + // and add a small space between them + m_barGraph->setBarThickness(1.0f); + m_barGraph->setBarSpacing(QSizeF(0.2, 0.2)); + +#ifndef USE_STATIC_DATA + // Set up sample space; make it as deep as it's wide + m_barGraph->rowAxis()->setRange(0, m_rowCount); + m_barGraph->columnAxis()->setRange(0, m_columnCount); + m_tableWidget->setColumnCount(m_columnCount); + + // Set selection mode to full + m_barGraph->setSelectionMode(QAbstract3DGraph::SelectionItemRowAndColumn); + + // Hide axis labels by explicitly setting one empty string as label list + m_barGraph->rowAxis()->setLabels(QStringList(QString())); + m_barGraph->columnAxis()->setLabels(QStringList(QString())); + + m_barGraph->seriesList().at(0)->setItemLabelFormat(QStringLiteral("@valueLabel")); +#else + // Set selection mode to slice row + m_barGraph->setSelectionMode( + QAbstract3DGraph::SelectionItemAndRow | QAbstract3DGraph::SelectionSlice); + m_surfaceGraph->setSelectionMode( + QAbstract3DGraph::SelectionItemAndRow | QAbstract3DGraph::SelectionSlice); +#endif +} + +GraphDataGenerator::~GraphDataGenerator() +{ + if (m_dataTimer) { + m_dataTimer->stop(); + delete m_dataTimer; + } + delete m_barGraph; + delete m_surfaceGraph; +} + +void GraphDataGenerator::start() +{ +#ifndef USE_STATIC_DATA + m_dataTimer = new QTimer(); + m_dataTimer->setTimerType(Qt::CoarseTimer); + QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::addRow); + m_dataTimer->start(0); + m_tableWidget->setFixedWidth(m_graph->width()); +#else + setupModel(); + + // Table needs to be shown before the size of its headers can be accurately obtained, + // so we postpone it a bit + m_dataTimer = new QTimer(); + m_dataTimer->setSingleShot(true); + QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::fixTableSize); + m_dataTimer->start(0); +#endif +} + +void GraphDataGenerator::setupModel() +{ + // Set up row and column names + QStringList days; + days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday"; + QStringList weeks; + weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5"; + + // Set up data Mon Tue Wed Thu Fri Sat Sun + float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 10.0f}, // week 1 + {0.5f, 1.0f, 3.0f, 1.0f, 2.0f, 2.0f, 3.0f}, // week 2 + {1.0f, 1.0f, 2.0f, 1.0f, 4.0f, 4.0f, 4.0f}, // week 3 + {0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4 + {3.0f, 3.0f, 6.0f, 2.0f, 2.0f, 1.0f, 1.0f}}; // week 5 + + // Add labels + m_barGraph->rowAxis()->setTitle("Week of year"); + m_barGraph->columnAxis()->setTitle("Day of week"); + m_barGraph->valueAxis()->setTitle("Hours spent on the Internet"); + m_barGraph->valueAxis()->setLabelFormat("%.1f h"); + + m_surfaceGraph->axisZ()->setTitle("Week of year"); + m_surfaceGraph->axisX()->setTitle("Day of week"); + m_surfaceGraph->axisY()->setTitle("Hours spent on the Internet"); + m_surfaceGraph->axisY()->setLabelFormat("%.1f h"); + + m_tableWidget->setRowCount(5); + m_tableWidget->setColumnCount(7); + m_tableWidget->setHorizontalHeaderLabels(days); + m_tableWidget->setVerticalHeaderLabels(weeks); + m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_tableWidget->setCurrentCell(-1, -1); + + for (int week = 0; week < weeks.size(); week++) { + for (int day = 0; day < days.size(); day++) { + QModelIndex index = m_tableWidget->model()->index(week, day); + m_tableWidget->model()->setData(index, hours[week][day]); + } + } +} + +void GraphDataGenerator::addRow() +{ + m_tableWidget->model()->insertRow(0); + if (m_tableWidget->model()->rowCount() > m_rowCount) + m_tableWidget->model()->removeRow(m_rowCount); + for (int i = 0; i < m_columnCount; i++) { + QModelIndex index = m_tableWidget->model()->index(0, i); + m_tableWidget->model()->setData(index, + ((float)i / (float)m_columnCount) / 2.0f + (float)(rand() % 30) / 100.0f); + } + m_tableWidget->resizeColumnsToContents(); +} + +void GraphDataGenerator::selectFromTable(const QPoint &selection) +{ + m_tableWidget->setFocus(); + m_tableWidget->setCurrentCell(selection.x(), selection.y()); +} + +void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn, + int previousRow, int previousColumn) +{ + Q_UNUSED(previousRow) + Q_UNUSED(previousColumn) + m_barGraph->seriesList().at(0)->setSelectedBar(QPoint(currentRow, currentColumn)); + m_surfaceGraph->seriesList().at(0)->setSelectedPoint(QPoint(currentRow, currentColumn)); +} + +void GraphDataGenerator::fixTableSize() +{ + int width = m_tableWidget->horizontalHeader()->length(); + width += m_tableWidget->verticalHeader()->width(); + m_tableWidget->setFixedWidth(width + 2); + int height = m_tableWidget->verticalHeader()->length(); + height += m_tableWidget->horizontalHeader()->height(); + m_tableWidget->setFixedHeight(height + 2); +} + +void GraphDataGenerator::changeSelectedButtonClicked() +{ + // Change all selected cells to a random value 1-10 + QVariant value = QVariant::fromValue(float((rand() % 10) + 1)); + QList<QTableWidgetItem *> selectedItems = m_tableWidget->selectedItems(); + foreach (QTableWidgetItem *item, selectedItems) + item->setData(Qt::DisplayRole, value); +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Q3DBars *barGraph = new Q3DBars(); + Q3DSurface *surfaceGraph = new Q3DSurface(); + QWidget *barContainer = QWidget::createWindowContainer(barGraph); + QWidget *surfaceContainer = QWidget::createWindowContainer(surfaceGraph); + + barContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + barContainer->setFocusPolicy(Qt::StrongFocus); + surfaceContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + surfaceContainer->setFocusPolicy(Qt::StrongFocus); + + QWidget widget; + QVBoxLayout *mainLayout = new QVBoxLayout(&widget); + QHBoxLayout *graphLayout = new QHBoxLayout(); + QVBoxLayout *buttonLayout = new QVBoxLayout(); + QHBoxLayout *bottomLayout = new QHBoxLayout(); + QTableWidget *tableWidget = new QTableWidget(&widget); + QPushButton *changeSelectedButton = new QPushButton(&widget); + changeSelectedButton->setText(QStringLiteral("Change Selected")); + + buttonLayout->addWidget(changeSelectedButton); + graphLayout->addWidget(barContainer); + graphLayout->addWidget(surfaceContainer); + bottomLayout->addLayout(buttonLayout); + bottomLayout->addWidget(tableWidget); + mainLayout->addLayout(graphLayout); + mainLayout->addLayout(bottomLayout); + + tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + tableWidget->setAlternatingRowColors(true); + widget.setWindowTitle(QStringLiteral("Hours spent on the Internet")); + + // Since we are dealing with QTableWidget, the model will already have data sorted properly + // into rows and columns, so we simply set useModelCategories property to true to utilize this. + QItemModelBarDataProxy *barProxy = new QItemModelBarDataProxy(tableWidget->model()); + QItemModelSurfaceDataProxy *surfaceProxy = new QItemModelSurfaceDataProxy(tableWidget->model()); + barProxy->setUseModelCategories(true); + surfaceProxy->setUseModelCategories(true); + QBar3DSeries *barSeries = new QBar3DSeries(barProxy); + QSurface3DSeries *surfaceSeries = new QSurface3DSeries(surfaceProxy); + barSeries->setMesh(QAbstract3DSeries::MeshPyramid); + barGraph->addSeries(barSeries); + surfaceGraph->addSeries(surfaceSeries); + + GraphDataGenerator generator(barGraph, surfaceGraph, tableWidget); + QObject::connect(barSeries, &QBar3DSeries::selectedBarChanged, &generator, + &GraphDataGenerator::selectFromTable); + QObject::connect(surfaceSeries, &QSurface3DSeries::selectedPointChanged, &generator, + &GraphDataGenerator::selectFromTable); + QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator, + &GraphDataGenerator::selectedFromTable); + QObject::connect(changeSelectedButton, &QPushButton::clicked, &generator, + &GraphDataGenerator::changeSelectedButtonClicked); + + QSize screenSize = barGraph->screen()->size(); + widget.resize(QSize(screenSize.width() / 2, screenSize.height() / 2)); + widget.show(); + generator.start(); + return app.exec(); +} diff --git a/tests/tests.pro b/tests/tests.pro index 613534e9..7b690c7d 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -14,7 +14,8 @@ SUBDIRS += barstest \ qmldynamicdata \ multigraphs \ directional \ - qmlmultiwindow + qmlmultiwindow \ + itemmodeltest #SUBDIRS += kinectsurface |