Commit bba28d17 authored by Volker Krause's avatar Volker Krause
Browse files

Properly show non-scalar content too in DataModel

parent ffc9311e
......@@ -19,18 +19,45 @@
#include <rest/restapi.h>
#include <rest/restclient.h>
#include <core/ratioset.h>
#include <core/sample.h>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <algorithm>
using namespace UserFeedback::Analyzer;
static QString mapToString(const QVariantMap &map)
{
QStringList l;
l.reserve(map.size());
for (auto it = map.begin(); it != map.end(); ++it) {
if (it.value().type() == QVariant::Map)
l.push_back(it.key() + QLatin1String(": {") + mapToString(it.value().toMap()) + QLatin1Char('}'));
else
l.push_back(it.key() + QLatin1String(": ") + it.value().toString());
}
return l.join(QLatin1String(", "));
}
static QString listToString(const QVariantList &list)
{
QStringList l;
l.reserve(list.size());
for (const auto &v : list)
l.push_back(mapToString(v.toMap()));
return QLatin1String("[{") + l.join(QLatin1String("}, {")) + QLatin1String("}]");
}
QString DataModel::Column::name() const
{
if (entry.dataType() == SchemaEntry::Scalar)
return entry.name() + QLatin1Char('.') + element.name();
return entry.name();
}
DataModel::DataModel(QObject *parent) : QAbstractTableModel(parent)
{
}
......@@ -52,14 +79,28 @@ void DataModel::setProduct(const Product& product)
m_product = product;
m_columns.clear();
for (const auto &entry : product.schema()) {
for (const auto &elem : entry.elements())
m_columns.push_back({entry, elem});
if (entry.dataType() == SchemaEntry::Scalar) {
for (const auto &elem : entry.elements())
m_columns.push_back({entry, elem});
} else {
m_columns.push_back({entry, {}});
}
}
m_data.clear();
reload();
endResetModel();
}
void DataModel::setSamples(const QVector<Sample> &samples)
{
beginResetModel();
m_data = samples;
std::sort(m_data.begin(), m_data.end(), [](const Sample &lhs, const Sample &rhs) {
return lhs.timestamp() < rhs.timestamp();
});
endResetModel();
}
void UserFeedback::Analyzer::DataModel::reload()
{
if (!m_restClient || !m_restClient->isConnected() || !m_product.isValid())
......@@ -68,12 +109,8 @@ void UserFeedback::Analyzer::DataModel::reload()
auto reply = RESTApi::listSamples(m_restClient, m_product);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error() == QNetworkReply::NoError) {
beginResetModel();
m_data = Sample::fromJson(reply->readAll(), m_product);
std::sort(m_data.begin(), m_data.end(), [](const Sample &lhs, const Sample &rhs) {
return lhs.timestamp() < rhs.timestamp();
});
endResetModel();
const auto samples = Sample::fromJson(reply->readAll(), m_product);
setSamples(samples);
}
});
}
......@@ -101,12 +138,15 @@ QVariant DataModel::data(const QModelIndex &index, int role) const
if (index.column() == 0)
return sample.timestamp();
const auto col = m_columns.at(index.column() - 1);
const auto v = sample.value(col.entry.name() + QLatin1Char('.') + col.element.name());
if (v.type() == QVariant::StringList)
return v.toStringList().join(QStringLiteral(", "));
if (v.userType() == qMetaTypeId<RatioSet>())
return v.value<RatioSet>().displayString();
return v;
const auto v = sample.value(col.name());
switch (col.entry.dataType()) {
case SchemaEntry::Scalar:
return v;
case SchemaEntry::List:
return listToString(v.toList());
case SchemaEntry::Map:
return mapToString(v.toMap());
}
} else if (role == SampleRole) {
return QVariant::fromValue(m_data.at(index.row()));
} else if (role == AllSamplesRole) {
......@@ -122,7 +162,7 @@ QVariant DataModel::headerData(int section, Qt::Orientation orientation, int rol
if (section == 0)
return tr("Timestamp");
const auto col = m_columns.at(section - 1);
return QString(col.entry.name() + QLatin1Char('.') + col.element.name());
return QString(col.name());
}
return QAbstractTableModel::headerData(section, orientation, role);
}
......@@ -45,6 +45,7 @@ public:
void setRESTClient(RESTClient *client);
void setProduct(const Product &product);
void setSamples(const QVector<Sample> &samples);
void reload();
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
......@@ -57,6 +58,8 @@ private:
struct Column {
SchemaEntry entry;
SchemaEntryElement element;
QString name() const;
};
QVector<Column> m_columns;
RESTClient *m_restClient = nullptr;
......
......@@ -15,6 +15,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <analyzer/core/sample.h>
#include <analyzer/core/schemaentrytemplates.h>
#include <analyzer/model/datamodel.h>
......@@ -30,6 +31,16 @@ using namespace UserFeedback::Analyzer;
class DataModelTest : public QObject
{
Q_OBJECT
private:
int findColumn(QAbstractItemModel *model, const QString &name)
{
for (int i = 0; i < model->columnCount(); ++i) {
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == name)
return i;
}
return -1;
}
private slots:
void initTestCase()
{
......@@ -37,7 +48,7 @@ private slots:
QStandardPaths::setTestModeEnabled(true);
}
void testDataModel()
void testEmptyDataModel()
{
DataModel model;
ModelTest modelTest(&model);
......@@ -52,6 +63,51 @@ private slots:
model.setProduct(p);
QVERIFY(model.columnCount() > 8);
}
void testDataModelContent()
{
DataModel model;
ModelTest modelTest(&model);
Product p;
p.setSchema(SchemaEntryTemplates::availableTemplates());
p.setName(QStringLiteral("org.kde.UserFeedback.UnitTest"));
model.setProduct(p);
auto samples = Sample::fromJson(R"([{
"id": 42,
"timestamp": "2016-11-27 16:09:06",
"platform": { "os": "linux", "version": "suse" },
"applicationVersion": { "value": "1.9.84" },
"screens": [ { "width": 1920, "height": 1200 }, { "width": 640, "height": 480 } ],
"newPropertyRatio": { "value1": { "property": 0.55 }, "value2": { "property": 0.45 } }
}, {
"id": 43,
"timestamp": "2016-12-09 12:00:00",
"platform": { "os": "linux", "version": "suse" },
"applicationVersion": { "value": "1.9.84" },
"screens": [ { "width": 1920, "height": 1200 } ],
"newPropertyRatio": { "value1": { "property": 0.1 }, "value2": { "property": 0.9 } }
}])", p);
QCOMPARE(samples.size(), 2);
model.setSamples(samples);
QCOMPARE(model.rowCount(), 2);
auto colIdx = findColumn(&model, QLatin1String("platform.os"));
QCOMPARE(model.index(0, colIdx).data(Qt::DisplayRole).toString(), QLatin1String("linux"));
colIdx = findColumn(&model, QLatin1String("platform.version"));
QCOMPARE(model.index(0, colIdx).data(Qt::DisplayRole).toString(), QLatin1String("suse"));
colIdx = findColumn(&model, QLatin1String("applicationVersion.value"));
QCOMPARE(model.index(0, colIdx).data(Qt::DisplayRole).toString(), QLatin1String("1.9.84"));
colIdx = findColumn(&model, QLatin1String("screens"));
QCOMPARE(model.index(0, colIdx).data(Qt::DisplayRole).toString(), QLatin1String("[{height: 1200, width: 1920}, {height: 480, width: 640}]"));
colIdx = findColumn(&model, QLatin1String("newPropertyRatio"));
QCOMPARE(model.index(0, colIdx).data(Qt::DisplayRole).toString(), QLatin1String("value1: {property: 0.55}, value2: {property: 0.45}"));
const auto sample = model.index(1, 1).data(DataModel::SampleRole).value<Sample>();
QCOMPARE(sample.timestamp().date(), QDate(2016, 12, 9));
}
};
QTEST_MAIN(DataModelTest)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment