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

Allow to name aggregations

Makes both the aggregation editor and the analytics view easier to
understand.
parent 62cc484d
......@@ -28,8 +28,8 @@ class AggregationTest extends AbstractDatastoreTest
$this->assertCount(0, $aggrs);
$json = '[
{ "type": "category", "elements": [ { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "elem11" } ] },
{ "type": "numeric", "elements": [ { "type": "size", "schemaEntry": "entry2" } ] }
{ "type": "category", "name": "category elem11", "elements": [ { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "elem11" } ] },
{ "type": "numeric", "name": "size: entry2", "elements": [ { "type": "size", "schemaEntry": "entry2" } ] }
]';
$aggrs = Aggregation::fromJson(json_decode($json));
$this->assertCount(2, $aggrs);
......@@ -37,10 +37,12 @@ class AggregationTest extends AbstractDatastoreTest
$a = $aggrs[0];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('category', $a->type);
$this->assertEquals('category elem11', $a->name);
$this->assertCount(1, $a->elements);
$a = $aggrs[1];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('numeric', $a->type);
$this->assertEquals('size: entry2', $a->name);
$this->assertCount(1, $a->elements);
}
......@@ -70,6 +72,7 @@ class AggregationTest extends AbstractDatastoreTest
$a = new Aggregation;
$a->type = 'xy';
$a->name = 'n1';
$a->elements = json_decode('[
{ "type": "value", "schemaEntry": "entry2", "schemaEntryElement": "element21" },
{ "type": "value", "schemaEntry": "entry2", "schemaEntryElement": "element22" }
......@@ -82,6 +85,7 @@ class AggregationTest extends AbstractDatastoreTest
$a = $aggrs[0];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('xy', $a->type);
$this->assertEquals('n1', $a->name);
$this->assertCount(2, $a->elements);
}
......@@ -104,7 +108,8 @@ class AggregationTest extends AbstractDatastoreTest
'nothing' => [ '' ],
'object' => [ '{}' ],
'array of non-objects' => [ '[1, 2, 3]' ],
'missing type' => [ '[{ "elements": [] }]' ]
'missing type' => [ '[{ "elements": [] }]' ],
'missing name' => [ '[{ "type": "category", "elements": [] }]' ]
];
}
......
......@@ -86,17 +86,20 @@
</table>
<table name="tbl_aggregation">
<column>col_id</column>
<column>col_name</column>
<column>col_product_id</column>
<column>col_type</column>
<column>col_elements</column>
<row>
<value>201</value>
<value>Category: entry1.elem11</value>
<value>2</value>
<value>category</value>
<value>[ { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "element11" } ]</value>
</row>
<row>
<value>202</value>
<value>entry2 size distribution</value>
<value>2</value>
<value>numeric</value>
<value>[ { "type": "size", "schemaEntry": "entry2" } ]</value>
......
......@@ -51,7 +51,7 @@ class ProductTest extends AbstractDatastoreTest
]
}
],
"aggregation": [ { "type": "category", "elements": [
"aggregation": [ { "type": "category", "name": "n1", "elements": [
{ "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "element1" }
] } ]
}');
......@@ -85,6 +85,7 @@ class ProductTest extends AbstractDatastoreTest
array_push($p->schema, $entry);
$a = new Aggregation;
$a->type = 'numeric';
$a->name = 'n1';
$a->elements = json_decode('[{ "type": "size", "schemaEntry": "entry1" }]');
array_push($p->aggregation, $a);
......@@ -99,7 +100,7 @@ class ProductTest extends AbstractDatastoreTest
]
}
],
"aggregation": [ { "type": "numeric", "elements": [
"aggregation": [ { "type": "numeric", "name": "n1", "elements": [
{ "type": "size", "schemaEntry": "entry1" }
] } ]
}');
......@@ -192,12 +193,14 @@ class ProductTest extends AbstractDatastoreTest
"aggregation": [
{
"type": "category",
"name": "n1",
"elements": [
{ "type": "value", "schemaEntry": "entryA", "schemaEntryElement": "elementA1" }
]
},
{
"type": "ratio_set",
"name": "n2",
"elements": [
{ "type": "value", "schemaEntry": "entryB", "schemaEntryElement": "elementB1" }
]
......@@ -238,6 +241,7 @@ class ProductTest extends AbstractDatastoreTest
"aggregation": [
{
"type": "ratio_set",
"name": "n2",
"elements": [
{ "type": "value", "schemaEntry": "entryB", "schemaEntryElement": "elementB1" }
]
......@@ -274,12 +278,14 @@ class ProductTest extends AbstractDatastoreTest
"aggregation": [
{
"type": "category",
"name": "n1",
"elements": [
{ "type": "value", "schemaEntry": "entryA", "schemaEntryElement": "elementA1" }
]
},
{
"type": "xy",
"name": "n3",
"elements": [
{ "type": "value", "schemaEntry": "entryC", "schemaEntryElement": "elementC1" },
{ "type": "value", "schemaEntry": "entryC", "schemaEntryElement": "elementC2" }
......@@ -311,6 +317,7 @@ class ProductTest extends AbstractDatastoreTest
"aggregation": [
{
"type": "numeric",
"name": "n4",
"elements": [
{ "type": "size", "schemaEntry": "entry1" }
]
......
......@@ -8,6 +8,7 @@
"type": "value"
}
],
"name": "Application Version Distribution",
"type": "category"
},
{
......@@ -18,6 +19,7 @@
"type": "value"
}
],
"name": "Dial Ratio Distribution",
"type": "ratio_set"
},
{
......@@ -28,6 +30,7 @@
"type": "value"
}
],
"name": "OS Distribution",
"type": "category"
},
{
......@@ -38,6 +41,7 @@
"type": "value"
}
],
"name": "Qt Version Distribution",
"type": "category"
},
{
......@@ -47,6 +51,7 @@
"type": "size"
}
],
"name": "Amount of Screens",
"type": "category"
},
{
......@@ -57,6 +62,7 @@
"type": "value"
}
],
"name": "Start Count Distribution",
"type": "numeric"
},
{
......@@ -67,6 +73,7 @@
"type": "value"
}
],
"name": "Usage Time Distribution",
"type": "numeric"
},
{
......@@ -77,6 +84,7 @@
"type": "value"
}
],
"name": "DPI Distribution",
"type": "numeric"
}
],
......
......@@ -8,6 +8,7 @@
"type": "value"
}
],
"name": "Application Version Distribution",
"type": "category"
},
{
......@@ -18,6 +19,7 @@
"type": "value"
}
],
"name": "View Ratio Distribution",
"type": "ratio_set"
},
{
......@@ -28,6 +30,7 @@
"type": "value"
}
],
"name": "OS Distribution",
"type": "category"
},
{
......@@ -38,6 +41,7 @@
"type": "value"
}
],
"name": "Qt Version Distribution",
"type": "category"
},
{
......@@ -48,6 +52,7 @@
"type": "value"
}
],
"name": "Start Count Distribution",
"type": "numeric"
},
{
......@@ -58,6 +63,7 @@
"type": "value"
}
],
"name": "Usage Count Distribution",
"type": "numeric"
}
],
......
......@@ -44,6 +44,11 @@ void Aggregator::setSourceModel(QAbstractItemModel* model)
m_sourceModel = model;
}
QString Aggregator::displayName() const
{
return m_aggregation.name();
}
Aggregator::ChartModes Aggregator::chartModes() const
{
return None;
......
......@@ -53,7 +53,7 @@ public:
QAbstractItemModel *sourceModel() const;
void setSourceModel(QAbstractItemModel *model);
virtual QString displayName() const = 0;
virtual QString displayName() const;
virtual ChartModes chartModes() const;
......
......@@ -161,7 +161,7 @@ void AnalyticsView::setProduct(const Product& product)
auto totalsAggr = new TotalAggregator;
m_aggregators.push_back(totalsAggr);
totalsAggr->setSourceModel(m_timeAggregationModel);
ui->chartType->addItem(tr("Samples"), QVariant::fromValue<Aggregator*>(totalsAggr));
ui->chartType->addItem(totalsAggr->displayName(), QVariant::fromValue<Aggregator*>(totalsAggr));
foreach (const auto &aggr, product.aggregations()) {
auto aggregator = createAggregator(aggr);
......
......@@ -48,12 +48,6 @@ Aggregator::ChartModes CategoryAggregator::chartModes() const
return modes;
}
QString CategoryAggregator::displayName() const
{
const auto e = aggregation().elements().at(0);
return e.schemaEntry().name();
}
QAbstractItemModel* CategoryAggregator::timeAggregationModel()
{
if (!m_model && !aggregation().elements().isEmpty()) {
......
......@@ -34,7 +34,6 @@ public:
~CategoryAggregator();
ChartModes chartModes() const override;
QString displayName() const override;
QAbstractItemModel* timeAggregationModel() override;
QtCharts::QChart* timelineChart() override;
QtCharts::QChart* singlularChart() override;
......
......@@ -41,12 +41,6 @@ Aggregator::ChartModes NumericAggregator::chartModes() const
return modes;
}
QString NumericAggregator::displayName() const
{
const auto e = aggregation().elements().at(0);
return e.schemaEntry().name();
}
QAbstractItemModel* NumericAggregator::timeAggregationModel()
{
if (!m_model && !aggregation().elements().isEmpty()) {
......
......@@ -34,7 +34,6 @@ public:
~NumericAggregator();
ChartModes chartModes() const override;
QString displayName() const override;
QAbstractItemModel* timeAggregationModel() override;
QtCharts::QChart* timelineChart() override;
......
......@@ -44,12 +44,6 @@ Aggregator::ChartModes RatioSetAggregator::chartModes() const
return modes;
}
QString RatioSetAggregator::displayName() const
{
const auto e = aggregation().elements().at(0);
return e.schemaEntry().name();
}
QAbstractItemModel* RatioSetAggregator::timeAggregationModel()
{
if (!m_model && !aggregation().elements().isEmpty()) {
......
......@@ -34,7 +34,6 @@ public:
~RatioSetAggregator();
ChartModes chartModes() const override;
QString displayName() const override;
QAbstractItemModel* timeAggregationModel() override;
QtCharts::QChart* timelineChart() override;
QtCharts::QChart* singlularChart() override;
......
......@@ -46,6 +46,16 @@ void Aggregation::setType(Aggregation::Type t)
m_type = t;
}
QString Aggregation::name() const
{
return m_name;
}
void Aggregation::setName(const QString& name)
{
m_name = name;
}
QVector<AggregationElement> Aggregation::elements() const
{
return m_elements;
......@@ -60,6 +70,7 @@ QJsonObject Aggregation::toJsonObject() const
{
QJsonObject obj;
obj.insert(QStringLiteral("type"), QLatin1String(aggregation_types_table[m_type].name));
obj.insert(QStringLiteral("name"), m_name);
QJsonArray elems;
for (const auto &e : m_elements)
elems.push_back(e.toJsonObject());
......@@ -78,6 +89,7 @@ QVector<Aggregation> Aggregation::fromJson(const Product &product, const QJsonAr
Aggregation aggr;
aggr.setType(Util::stringToEnum<Aggregation::Type>(obj.value(QLatin1String("type")).toString(), aggregation_types_table));
aggr.setName(obj.value(QLatin1String("name")).toString());
aggr.setElements(AggregationElement::fromJson(product, obj.value(QLatin1String("elements")).toArray()));
aggrs.push_back(aggr);
}
......
......@@ -48,6 +48,9 @@ public:
Type type() const;
void setType(Type t);
QString name() const;
void setName(const QString &name);
QVector<AggregationElement> elements() const;
void setElements(const QVector<AggregationElement> &elements);
......@@ -56,6 +59,7 @@ public:
private:
Type m_type = None;
QString m_name;
QVector<AggregationElement> m_elements;
};
......
......@@ -44,7 +44,7 @@ void AggregationEditorModel::setProduct(const Product& product)
int AggregationEditorModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return 2;
return 3;
}
int AggregationEditorModel::rowCount(const QModelIndex& parent) const
......@@ -63,8 +63,10 @@ QVariant AggregationEditorModel::data(const QModelIndex& index, int role) const
const auto aggr = m_product.aggregations().at(index.row());
switch (index.column()) {
case 0:
return Util::enumToString(aggr.type());
return aggr.name();
case 1:
return Util::enumToString(aggr.type());
case 2:
if (aggr.elements().isEmpty())
return tr("<none>");
return aggr.elements().at(0).displayString();
......@@ -73,8 +75,10 @@ QVariant AggregationEditorModel::data(const QModelIndex& index, int role) const
const auto aggr = m_product.aggregations().at(index.row());
switch (index.column()) {
case 0:
return QVariant::fromValue(aggr.type());
return aggr.name();
case 1:
return QVariant::fromValue(aggr.type());
case 2:
if (aggr.elements().isEmpty())
return QVariant::fromValue(AggregationElement());
return QVariant::fromValue(aggr.elements().at(0));
......@@ -88,8 +92,9 @@ QVariant AggregationEditorModel::headerData(int section, Qt::Orientation orienta
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0: return tr("Type");
case 1: return tr("Element");
case 0: return tr("Name");
case 1: return tr("Type");
case 2: return tr("Element");
}
}
......@@ -114,9 +119,12 @@ bool AggregationEditorModel::setData(const QModelIndex& index, const QVariant& v
auto &aggr = aggrs[index.row()];
switch (index.column()) {
case 0:
aggr.setType(value.value<Aggregation::Type>());
aggr.setName(value.toString());
break;
case 1:
aggr.setType(value.value<Aggregation::Type>());
break;
case 2:
aggr.setElements({ value.value<AggregationElement>() });
break;
}
......
......@@ -16,6 +16,7 @@
"aggregation": [
{
"type": "category",
"name": "Application Version Distribution",
"elements": [ { "type": "value", "schemaEntry": "applicationVersion", "schemaEntryElement": "value" } ]
}
]
......
......@@ -17,7 +17,9 @@
]
}
],
"aggregation": [
{ "type": "category", "elements": [ { "type": "value", "schemaEntry": "platform", "schemaEntryElement": "os" } ] }
]
"aggregation": [ {
"type": "category",
"name": "OS Distribution",
"elements": [ { "type": "value", "schemaEntry": "platform", "schemaEntryElement": "os" } ]
} ]
}
......@@ -16,6 +16,7 @@
"aggregation": [
{
"type": "ratio_set",
"name": "Property Ratio",
"elements": [ { "type": "value", "schemaEntry": "newPropertyRatio", "schemaEntryElement": "property" } ]
}
]
......
Markdown is supported
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