summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2013-10-10 11:15:47 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2013-10-10 12:27:13 +0300
commit062d16efb0a035643b5f46f6788845869cc4d300 (patch)
treeb68e2f452ce100078835c209d781b8420eba33a6
parent000c2cbd551f0d69997437b2ba0cc87773354520 (diff)
Document customproxy example
The screenshot needs to be retaken. Task-number: QTRD-2399 Change-Id: I216b082b9660ba756902a8c6bf9393039956f2f5 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--examples/audiolevels/doc/src/audiolevels.qdoc4
-rw-r--r--examples/customproxy/doc/src/customproxy.qdoc85
-rw-r--r--examples/customproxy/rainfallgraph.cpp22
-rw-r--r--examples/customproxy/variantbardatamapping.h8
-rw-r--r--examples/customproxy/variantbardataproxy.cpp8
-rw-r--r--examples/customproxy/variantbardataproxy.h4
-rw-r--r--examples/customproxy/variantdataset.h4
7 files changed, 124 insertions, 11 deletions
diff --git a/examples/audiolevels/doc/src/audiolevels.qdoc b/examples/audiolevels/doc/src/audiolevels.qdoc
index 8737c242..3d392487 100644
--- a/examples/audiolevels/doc/src/audiolevels.qdoc
+++ b/examples/audiolevels/doc/src/audiolevels.qdoc
@@ -28,6 +28,8 @@
in a bar graph. To increase the load for demonstration purposes, and to make the
graph little fancier, slightly modified data is used to fill multiple rows.
+ \image audiolevels-example.png
+
The interesting stuff happens in AudioLevels and AudioLevelsIODevice classes, so we
concentrate on those and skip explaining the basic Q3DBars functionality - for that see
\l{Bars Example}.
@@ -80,6 +82,4 @@
it does allocate some memory to store other optional bar properties besides the value.
In use cases where those optional properties are used, using memmove and memcpy would lead to
memory leaks, so use them with care.
-
- \image audiolevels-example.png
*/
diff --git a/examples/customproxy/doc/src/customproxy.qdoc b/examples/customproxy/doc/src/customproxy.qdoc
index 8bb02105..288a7149 100644
--- a/examples/customproxy/doc/src/customproxy.qdoc
+++ b/examples/customproxy/doc/src/customproxy.qdoc
@@ -26,5 +26,88 @@
\image customproxy-example.png
- TODO
+ The interesting thing about custom proxy example is the custom dataset and the corresponding
+ proxy usage, so we concentrate on that and skip explaining the basic Q3DBars functionality
+ - for that see \l{Bars Example}.
+
+ This example defines a simple flexible data set \c VariantDataSet where each data item is a
+ a variant list. Each item can have multiple different values, identified by their index in
+ the list. In this example, the data set is storing monthly rainfall data, where value in
+ index one is the year, index two contains the month, and the third value has the amount
+ of rainfall in that month.
+
+ The custom proxy we provide here is similar to item model based proxies provided by Qt
+ Data Visualization in that it requires a mapping object to interpret the data.
+
+ Let's take a closer look at the custom classes:
+
+ \section1 VariantDataSet
+
+ \c VariantDataSet class provides a simple API:
+
+ \snippet ../examples/customproxy/variantdataset.h 1
+ \dots 0
+ \codeline
+ \snippet ../examples/customproxy/variantdataset.h 0
+
+ As you can see, the data items are simply QVariantList objects, and the data can be added either
+ singly or in lists. The only additional functionality provided is clearing the data set and querying
+ for a reference to the data contained in the set. Signals are emitted when data is added or the set
+ is cleared.
+
+ \section1 VariantBarDataProxy
+
+ \c VariantBarDataProxy is a subclass of QBarDataProxy and provides a simple API of just getters
+ and setters for the data set and the mapping:
+
+ \snippet ../examples/customproxy/variantbardataproxy.h 0
+ \dots 0
+ \codeline
+ \snippet ../examples/customproxy/variantbardataproxy.h 1
+
+ On the implementation side, the proxy listens for the changes in the data set and the mapping,
+ and resolves the data set if any changes are detected. It is not particularly efficient
+ implementation in that any change will cause re-resolving of the entire data set, but that is not
+ an issue for this example. The interesting part is the \c resolveDataSet() method:
+
+ \snippet ../examples/customproxy/variantbardataproxy.cpp 0
+
+ In \c resolveDataSet() method we sort the variant data values into rows and columns based on the
+ mapping. This is very similar to how QItemModelBarDataProxy handles mapping, except we use
+ list indexes instead of item model roles here. Once the values are sorted, we generate \c QBarDataArray
+ out of them, and call \c resetArray() method on the parent class.
+
+ \section1 VariantBarDataMapping
+
+ \c VariantBarDataMapping stores the mapping information between \c VariantDataSet data item indexes
+ and rows, columns, and values of \c QBarDataArray. It also contains the lists of rows and columns to
+ be included in the resolved data:
+
+ \snippet ../examples/customproxy/variantbardatamapping.h 0
+ \dots 0
+ \codeline
+ \snippet ../examples/customproxy/variantbardatamapping.h 1
+ \dots 0
+ \codeline
+ \snippet ../examples/customproxy/variantbardatamapping.h 2
+ \dots 0
+ \codeline
+ \snippet ../examples/customproxy/variantbardatamapping.h 3
+
+ The primary way to use a \c VariantBarDataMapping object is to give the mappings already at the
+ constructor, though they can be set later individually or all together with \c remap() method.
+ A signal is emitted if mapping changes. It is basically a simplified version of
+ QItemModelBarDataMapping adapted to work with variant lists instead of item models.
+
+ \section1 RainfallGraph
+
+ \c RainfallGraph class handles the setup of the graph. The interesting part is the \c addDataSet()
+ method:
+
+ \snippet ../examples/customproxy/rainfallgraph.cpp 0
+
+ Bulk of that method is used for populating the variant data set. Once the set is populated,
+ visualizing the data is trivial with the help of our custom proxy:
+
+ \snippet ../examples/customproxy/rainfallgraph.cpp 1
*/
diff --git a/examples/customproxy/rainfallgraph.cpp b/examples/customproxy/rainfallgraph.cpp
index 41f72464..3a9f820a 100644
--- a/examples/customproxy/rainfallgraph.cpp
+++ b/examples/customproxy/rainfallgraph.cpp
@@ -55,6 +55,7 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall)
m_graph->columnAxis()->setTitle("Month");
m_graph->valueAxis()->setTitle("rainfall");
m_graph->valueAxis()->setLabelFormat("%d mm");
+ m_graph->valueAxis()->setSegmentCount(5);
m_graph->rowAxis()->setCategoryLabels(m_years);
m_graph->columnAxis()->setCategoryLabels(months);
@@ -73,11 +74,9 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall)
// Set theme
m_graph->setTheme(QDataVis::ThemeArmyBlue);
- // Set preset camera position
+ // Set camera position and zoom
m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetIsometricRightHigh);
-
- // Disable grid
- m_graph->setGridVisible(false);
+ m_graph->scene()->activeCamera()->setZoomLevel(75);
// Set window title
m_graph->setTitle(QStringLiteral("Monthly rainfall in Northern Finland"));
@@ -104,23 +103,30 @@ void RainfallGraph::updateYearsList(int start, int end)
m_rowCount = m_years.size();
}
+//! [0]
void RainfallGraph::addDataSet()
{
+ // Create a new variant data set and data item list
m_dataSet = new VariantDataSet;
VariantDataItemList *itemList = new VariantDataItemList;
+
+ // Read data from a data file into the data item list
QTextStream stream;
QFile dataFile(":/data/raindata.txt");
if (dataFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
stream.setDevice(&dataFile);
while (!stream.atEnd()) {
QString line = stream.readLine();
- if (line.startsWith("#"))
+ if (line.startsWith("#")) // Ignore comments
continue;
QStringList strList = line.split(",", QString::SkipEmptyParts);
+ // Each line has three data items: Year, month, and rainfall value
if (strList.size() < 3) {
qWarning() << "Invalid row read from data:" << line;
continue;
}
+ // Store year and month as strings, and rainfall value as double
+ // into a variant data item and add the item to the item list.
VariantDataItem *newItem = new VariantDataItem;
for (int i = 0; i < 2; i++)
newItem->append(strList.at(i).trimmed());
@@ -131,10 +137,14 @@ void RainfallGraph::addDataSet()
qWarning() << "Unable to open data file:" << dataFile.fileName();
}
+ //! [1]
+ // Add items to the data set and set it to the proxy
m_dataSet->addItems(itemList);
-
m_proxy->setDataSet(m_dataSet);
+ // Create new mapping for the data and set it to the proxy
m_mapping = new VariantBarDataMapping(0, 1, 2, m_years, m_numericMonths);
m_proxy->setMapping(m_mapping);
+ //! [1]
}
+//! [0]
diff --git a/examples/customproxy/variantbardatamapping.h b/examples/customproxy/variantbardatamapping.h
index 0204ddc8..9ccf1610 100644
--- a/examples/customproxy/variantbardatamapping.h
+++ b/examples/customproxy/variantbardatamapping.h
@@ -27,17 +27,21 @@ using namespace QtDataVisualization;
class VariantBarDataMapping : public QObject
{
Q_OBJECT
+ //! [0]
Q_PROPERTY(int rowIndex READ rowIndex WRITE setRowIndex)
Q_PROPERTY(int columnIndex READ columnIndex WRITE setColumnIndex)
Q_PROPERTY(int valueIndex READ valueIndex WRITE setValueIndex)
Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories)
Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories)
+ //! [0]
public:
explicit VariantBarDataMapping();
VariantBarDataMapping(const VariantBarDataMapping &other);
+ //! [1]
VariantBarDataMapping(int rowIndex, int columnIndex, int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories);
+ //! [1]
virtual ~VariantBarDataMapping();
VariantBarDataMapping &operator=(const VariantBarDataMapping &other);
@@ -54,11 +58,15 @@ public:
void setColumnCategories(const QStringList &categories);
const QStringList &columnCategories() const;
+ //! [2]
void remap(int rowIndex, int columnIndex, int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories);
+ //! [2]
signals:
+ //! [3]
void mappingChanged();
+ //! [3]
private:
// Indexes of the mapped items in the VariantDataItem
diff --git a/examples/customproxy/variantbardataproxy.cpp b/examples/customproxy/variantbardataproxy.cpp
index c907a1e3..887115b8 100644
--- a/examples/customproxy/variantbardataproxy.cpp
+++ b/examples/customproxy/variantbardataproxy.cpp
@@ -85,7 +85,7 @@ void VariantBarDataProxy::handleItemsAdded(int index, int count)
Q_UNUSED(count)
// Resolve new items
- resolveDataSet(); // TODO Resolving entire dataset is inefficient
+ resolveDataSet();
}
void VariantBarDataProxy::handleDataCleared()
@@ -100,8 +100,10 @@ void VariantBarDataProxy::handleMappingChanged()
}
// Resolve entire dataset into QBarDataArray.
+//! [0]
void VariantBarDataProxy::resolveDataSet()
{
+ // If we have no data or mapping, or the categories are not defined, simply clear the array
if (m_dataSet.isNull() || m_mapping.isNull() || !m_mapping->rowCategories().size()
|| !m_mapping->columnCategories().size()) {
resetArray(0);
@@ -123,7 +125,7 @@ void VariantBarDataProxy::resolveDataSet()
= item->at(valueIndex).toReal();
}
- // Create new data array from itemValueMap
+ // Create a new data array in format the parent class understands
QBarDataArray *newProxyArray = new QBarDataArray;
foreach (QString rowKey, rowList) {
QBarDataRow *newProxyRow = new QBarDataRow(columnList.size());
@@ -132,5 +134,7 @@ void VariantBarDataProxy::resolveDataSet()
newProxyArray->append(newProxyRow);
}
+ // Finally, reset the data array in the parent class
resetArray(newProxyArray);
}
+//! [0]
diff --git a/examples/customproxy/variantbardataproxy.h b/examples/customproxy/variantbardataproxy.h
index b931aa5c..6f6ba763 100644
--- a/examples/customproxy/variantbardataproxy.h
+++ b/examples/customproxy/variantbardataproxy.h
@@ -28,7 +28,9 @@
using namespace QtDataVisualization;
+//! [0]
class VariantBarDataProxy : public QBarDataProxy
+//! [0]
{
Q_OBJECT
@@ -37,6 +39,7 @@ public:
explicit VariantBarDataProxy(VariantDataSet *newSet, VariantBarDataMapping *mapping);
virtual ~VariantBarDataProxy();
+ //! [1]
// Doesn't gain ownership of the dataset, but does connect to it to listen for data changes.
void setDataSet(VariantDataSet *newSet);
VariantDataSet *dataSet();
@@ -46,6 +49,7 @@ public:
// Modifying mapping that is set to proxy will trigger dataset re-resolving.
void setMapping(VariantBarDataMapping *mapping);
VariantBarDataMapping *mapping();
+ //! [1]
public slots:
void handleItemsAdded(int index, int count);
diff --git a/examples/customproxy/variantdataset.h b/examples/customproxy/variantdataset.h
index 7906d4f5..6beb852f 100644
--- a/examples/customproxy/variantdataset.h
+++ b/examples/customproxy/variantdataset.h
@@ -25,8 +25,10 @@
using namespace QtDataVisualization;
+//! [1]
typedef QVariantList VariantDataItem;
typedef QList<VariantDataItem *> VariantDataItemList;
+//! [1]
class VariantDataSet : public QObject
{
@@ -36,6 +38,7 @@ public:
explicit VariantDataSet();
~VariantDataSet();
+ //! [0]
void clear();
int addItem(VariantDataItem *item);
@@ -46,6 +49,7 @@ public:
signals:
void itemsAdded(int index, int count);
void dataCleared();
+ //! [0]
private:
VariantDataItemList m_variantData;