KReport

How to Implement a Data Source

This section describes how to implement a data source for KReport.

As an example, this data source will simply wrap a QAbstractTableModel and will keep the current row in an attribute. It is the most simple data source that does not sort its data.

#include <KReportDataSource>
#include <QPointer>
class KReportTableModelDataSource : public KReportDataSource
{
public:
explicit KReportTableModelDataSource(QAbstractTableModel *model);
~KReportTableModelDataSource() override;
bool open() override;
bool close() override;
bool moveNext() override;
bool movePrevious() override;
bool moveFirst() override;
bool moveLast() override;
qint64 at() const override;
qint64 recordCount() const override;
int fieldNumber(const QString &field) const override;
QStringList fieldNames() const override;
QVariant value(int pos) const override;
QVariant value(const QString &field) const override;
QStringList dataSourceNames() const override;
private:
qint64 m_currentRow;
};

The constructor already receives the model with all the data that we need to extract, therefore in this case there is nothing to open or close.

#include "kreporttablemodeldatasource.h"
#include <QAbstractTableModel>
KReportTableModelDataSource::KReportTableModelDataSource(QAbstractTableModel *model)
, m_currentRow(0)
, m_model(&model)
{}
KReportTableModelDataSource::~KReportTableModelDataSource() {}
bool KReportTableModelDataSource::open()
{
// Nothing to do.
return true;
}
bool KReportTableModelDataSource::close()
{
// Nothing to do.
return true;
}

Next we will manage the current row by implementing the next, previous, first, and last methods. Those methods are called by KReport when traversing the data source within a report’s section.

bool KReportTableModelDataSource::moveNext()
{
if (m_currentRow >= recordCount() - 1) {
return false;
}
m_currentRow++;
return true;
}
bool KReportTableModelDataSource::movePrevious()
{
if (m_currentRow <= 0) {
return false;
}
m_currentRow--;
return true;
}
bool KReportTableModelDataSource::moveFirst()
{
m_currentRow = 0;
return true;
}
bool KReportTableModelDataSource::moveLast()
{
m_currentRow = recordCount() - 1;
return true;
}
qint64 KReportTableModelDataSource::at() const
{
return m_currentRow;
}

KReport needs to know how many rows there are in the data source.

qint64 KReportTableModelDataSource::recordCount() const
{
return m_model->rowCount();
}

It also needs to know the field count for each record, their names, and a way to reference them. All records need to have the same number of fields, exactly like the rows of a QAbstractTableModel. In this case, the field names will correspond to column’s names, and will use them as keys; the default behaviour of KReportDataSource::fieldKeys() is to return the output of KReportDataSource::fieldNames().

QStringList KReportTableModelDataSource::fieldNames() const
{
QStringList names;
for (int i = 0; i < m_model->columnCount(); i++) {
names << m_model->headerData(i, Qt::Horizontal).toString();
}
return names;
}
int KReportTableModelDataSource::fieldNumber(const QString &field) const
{
for (int i = 0; i < m_model->columnCount(); i++) {
if (m_model->headerData(i, Qt::Horizontal).toString() == field) {
return i;
}
}
return -1;
}

KReport will need to be able to read the value of a given field. The field is always in the current record and can be referenced by the key — the column’s name in this case — or by its position. Therefore we need to handle both cases.

QVariant KReportTableModelDataSource::value(int pos) const
{
return m_model->data(m_model->index(m_currentRow, pos));
}
QVariant KReportTableModelDataSource::value(const QString &field) const
{
return value(fieldNumber(field));
}

The last remaining method to implement is for data sources that can retrieve data from multiple sources. In this case there is one possible source, the QAbstractTableModel, and have nothing to return.

QStringList KReportTableModelDataSource::dataSourceNames() const
{
return QStringList();
}

Our data source is now ready to be used to render reports.

This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Apr 20 2021 23:06:59 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.