Commit 97f7cea1 authored by Volker Krause's avatar Volker Krause
Browse files

Start to refactor the aggregation code

We now have a dedicated class per aggregation handling model setup and
chart creation.
parent 7cea54e6
......@@ -37,8 +37,12 @@ set(analyzer_srcs
main.cpp
mainwindow.cpp
analytics/aggregator.cpp
analytics/analyticsview.cpp
analytics/categoryaggregator.cpp
analytics/chart.cpp
analytics/numericaggregator.cpp
analytics/ratiosetaggregator.cpp
schemaeditor/aggregationeditwidget.cpp
schemaeditor/schemaeditor.cpp
......
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aggregator.h"
using namespace UserFeedback::Analyzer;
Aggregator::Aggregator() = default;
Aggregator::~Aggregator() = default;
Aggregation Aggregator::aggregation() const
{
return m_aggregation;
}
void Aggregator::setAggregation(const Aggregation& aggr)
{
m_aggregation = aggr;
}
QAbstractItemModel* Aggregator::sourceModel() const
{
return m_sourceModel;
}
void Aggregator::setSourceModel(QAbstractItemModel* model)
{
m_sourceModel = model;
}
Aggregator::ChartModes Aggregator::chartModes() const
{
return None;
}
QAbstractItemModel* Aggregator::timeAggregationModel()
{
return nullptr;
}
QtCharts::QChart *Aggregator::singlularChart()
{
return nullptr;
}
QtCharts::QChart *Aggregator::timelineChart()
{
return nullptr;
}
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERFEEDBACK_ANALYZER_AGGREGATOR_H
#define USERFEEDBACK_ANALYZER_AGGREGATOR_H
#include <core/aggregation.h>
class QAbstractItemModel;
namespace QtCharts {
class QChart;
}
namespace UserFeedback {
namespace Analyzer {
class Aggregation;
class Aggregator
{
public:
explicit Aggregator();
virtual ~Aggregator();
enum ChartMode {
None = 0x0,
Singular = 0x1,
Timeline = 0x2
};
Q_DECLARE_FLAGS(ChartModes, ChartMode)
Aggregation aggregation() const;
void setAggregation(const Aggregation &aggr);
QAbstractItemModel *sourceModel() const;
void setSourceModel(QAbstractItemModel *model);
virtual QString displayName() const = 0;
virtual ChartModes chartModes() const;
virtual QAbstractItemModel *timeAggregationModel();
virtual QtCharts::QChart *singlularChart();
virtual QtCharts::QChart *timelineChart();
private:
QAbstractItemModel *m_sourceModel = nullptr;
Aggregation m_aggregation;
};
}}
Q_DECLARE_METATYPE(UserFeedback::Analyzer::Aggregator*)
Q_DECLARE_OPERATORS_FOR_FLAGS(UserFeedback::Analyzer::Aggregator::ChartModes)
#endif // USERFEEDBACK_ANALYZER_AGGREGATOR_H
......@@ -18,13 +18,14 @@
#include "analyticsview.h"
#include "ui_analyticsview.h"
#include "aggregator.h"
#include "categoryaggregator.h"
#include "chart.h"
#include "numericaggregator.h"
#include "ratiosetaggregator.h"
#include <model/aggregateddatamodel.h>
#include <model/categoryaggregationmodel.h>
#include <model/datamodel.h>
#include <model/numericaggregationmodel.h>
#include <model/ratiosetaggregationmodel.h>
#include <model/timeaggregationmodel.h>
#include <rest/restapi.h>
#include <core/aggregation.h>
......@@ -95,10 +96,7 @@ AnalyticsView::AnalyticsView(QWidget* parent) :
settings.endGroup();
ui->chartView->setChart(m_chart->chart());
connect(ui->chartType, &QComboBox::currentTextChanged, this, [this]() {
const auto model = ui->chartType->currentData().value<QAbstractItemModel*>();
m_chart->setModel(model);
});
connect(ui->chartType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AnalyticsView::chartSelected);
}
AnalyticsView::~AnalyticsView()
......@@ -128,56 +126,63 @@ void AnalyticsView::setProduct(const Product& product)
m_aggregatedDataModel->addSourceModel(m_timeAggregationModel);
ui->chartType->addItem(tr("Samples"), QVariant::fromValue(m_timeAggregationModel));
qDeleteAll(m_aggregators);
m_aggregators.clear();
foreach (const auto &aggr, product.aggregations()) {
switch (aggr.type()) {
case Aggregation::None:
break;
case Aggregation::Category:
{
if (aggr.elements().isEmpty())
break;
auto model = new CategoryAggregationModel(this);
model->setSourceModel(m_timeAggregationModel);
const auto e = aggr.elements().at(0);
model->setAggregationValue(e.schemaEntry().name() + QLatin1Char('.') + e.schemaEntryElement().name());
m_aggregationModels.push_back(model);
m_aggregatedDataModel->addSourceModel(model, e.schemaEntry().name());
ui->chartType->addItem(e.schemaEntry().name(), QVariant::fromValue(model));
break;
}
case Aggregation::Numeric:
{
if (aggr.elements().isEmpty())
break;
auto model = new NumericAggregationModel(this);
model->setSourceModel(m_timeAggregationModel);
const auto e = aggr.elements().at(0);
model->setAggregationValue(e.schemaEntry().name() + QLatin1Char('.') + e.schemaEntryElement().name());
m_aggregationModels.push_back(model);
m_aggregatedDataModel->addSourceModel(model, e.schemaEntry().name());
ui->chartType->addItem(e.schemaEntry().name(), QVariant::fromValue(model));
break;
}
case Aggregation::RatioSet:
{
if (aggr.elements().isEmpty())
break;
auto model = new RatioSetAggregationModel(this);
model->setSourceModel(m_timeAggregationModel);
const auto e = aggr.elements().at(0);
model->setAggregationValue(e.schemaEntry().name());
m_aggregationModels.push_back(model);
m_aggregatedDataModel->addSourceModel(model, e.schemaEntry().name());
ui->chartType->addItem(e.schemaEntry().name(), QVariant::fromValue(model));
break;
}
case Aggregation::XY:
// TODO
break;
auto aggregator = createAggregator(aggr);
if (!aggregator)
continue;
m_aggregators.push_back(aggregator);
if (auto model = aggregator->timeAggregationModel()) {
m_aggregatedDataModel->addSourceModel(model, aggregator->displayName());
// ### temporary
ui->chartType->addItem(aggregator->displayName(), QVariant::fromValue(model));
}
// if (aggregator->chartModes() != Aggregator::None)
// ui->chartType->addItem(aggregator->displayName(), QVariant::fromValue(aggregator));
}
}
void AnalyticsView::chartSelected()
{
const auto model = ui->chartType->currentData().value<QAbstractItemModel*>();
m_chart->setModel(model);
auto aggr = ui->chartType->currentData().value<Aggregator*>();
if (!aggr)
return;
// ui->chartView->setChart(aggr->timelineChart());
}
Aggregator* AnalyticsView::createAggregator(const Aggregation& aggr) const
{
Aggregator *aggregator = nullptr;
switch (aggr.type()) {
case Aggregation::None:
break;
case Aggregation::Category:
aggregator = new CategoryAggregator;
break;
case Aggregation::Numeric:
aggregator = new NumericAggregator;
break;
case Aggregation::RatioSet:
aggregator = new RatioSetAggregator;
break;
case Aggregation::XY:
break;
}
if (!aggregator)
return nullptr;
aggregator->setAggregation(aggr);
aggregator->setSourceModel(m_timeAggregationModel);
return aggregator;
}
void AnalyticsView::exportData()
{
const auto fileName = QFileDialog::getSaveFileName(this, tr("Export Data"));
......
......@@ -30,6 +30,7 @@ class QAbstractItemModel;
namespace UserFeedback {
namespace Analyzer {
class Aggregator;
class AggregatedDataModel;
class Chart;
class DataModel;
......@@ -55,6 +56,10 @@ signals:
void logMessage(const QString &msg);
private:
void chartSelected();
Aggregator* createAggregator(const Aggregation &aggr) const;
void exportData();
void importData();
......@@ -66,6 +71,8 @@ private:
QVector<QAbstractItemModel*> m_aggregationModels;
AggregatedDataModel *m_aggregatedDataModel;
Chart *m_chart;
QVector<Aggregator*> m_aggregators;
};
}
}
......
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "categoryaggregator.h"
#include <model/categoryaggregationmodel.h>
using namespace UserFeedback::Analyzer;
CategoryAggregator::CategoryAggregator() = default;
CategoryAggregator::~CategoryAggregator() = default;
Aggregator::ChartModes CategoryAggregator::chartModes() const
{
Aggregator::ChartModes modes = None;
if (aggregation().elements().size() == 1)
modes |= Timeline;
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()) {
m_model.reset(new CategoryAggregationModel);
m_model->setSourceModel(sourceModel());
const auto e = aggregation().elements().at(0);
m_model->setAggregationValue(e.schemaEntry().name() + QLatin1Char('.') + e.schemaEntryElement().name());
}
return m_model.get();
}
QtCharts::QChart* CategoryAggregator::timelineChart()
{
// TODO
return nullptr;
}
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERFEEDBACK_ANALYZER_CATEGORYAGGREGATOR_H
#define USERFEEDBACK_ANALYZER_CATEGORYAGGREGATOR_H
#include "aggregator.h"
#include <memory>
namespace UserFeedback {
namespace Analyzer {
class CategoryAggregationModel;
class CategoryAggregator : public Aggregator
{
public:
CategoryAggregator();
~CategoryAggregator();
ChartModes chartModes() const override;
QString displayName() const override;
QAbstractItemModel* timeAggregationModel() override;
QtCharts::QChart* timelineChart() override;
private:
std::unique_ptr<CategoryAggregationModel> m_model;
};
}}
#endif // USERFEEDBACK_ANALYZER_CATEGORYAGGREGATOR_H
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "numericaggregator.h"
#include <model/numericaggregationmodel.h>
using namespace UserFeedback::Analyzer;
NumericAggregator::NumericAggregator() = default;
NumericAggregator::~NumericAggregator() = default;
Aggregator::ChartModes NumericAggregator::chartModes() const
{
Aggregator::ChartModes modes = None;
if (aggregation().elements().size() == 1)
modes |= Timeline;
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()) {
m_model.reset(new NumericAggregationModel);
m_model->setSourceModel(sourceModel());
const auto e = aggregation().elements().at(0);
m_model->setAggregationValue(e.schemaEntry().name() + QLatin1Char('.') + e.schemaEntryElement().name());
}
return m_model.get();
}
QtCharts::QChart* NumericAggregator::timelineChart()
{
return nullptr;
}
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERFEEDBACK_ANALYZER_NUMERICAGGREGATOR_H
#define USERFEEDBACK_ANALYZER_NUMERICAGGREGATOR_H
#include "aggregator.h"
#include <memory>
namespace UserFeedback {
namespace Analyzer {
class NumericAggregationModel;
class NumericAggregator : public Aggregator
{
public:
NumericAggregator();
~NumericAggregator();
ChartModes chartModes() const override;
QString displayName() const override;
QAbstractItemModel* timeAggregationModel() override;
QtCharts::QChart* timelineChart() override;
private:
std::unique_ptr<NumericAggregationModel> m_model;
};
}}
#endif // USERFEEDBACK_ANALYZER_NUMERICAGGREGATOR_H
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ratiosetaggregator.h"
#include <model/ratiosetaggregationmodel.h>
using namespace UserFeedback::Analyzer;
RatioSetAggregator::RatioSetAggregator() = default;
RatioSetAggregator::~RatioSetAggregator() = default;
Aggregator::ChartModes RatioSetAggregator::chartModes() const
{
Aggregator::ChartModes modes = None;
if (aggregation().elements().size() == 1)
modes |= Timeline;
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()) {
m_model.reset(new RatioSetAggregationModel);
m_model->setSourceModel(sourceModel());
const auto e = aggregation().elements().at(0);
m_model->setAggregationValue(e.schemaEntry().name());
}
return m_model.get();
}
QtCharts::QChart* RatioSetAggregator::timelineChart()
{
return nullptr;
}
/*
Copyright (C) 2017 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERFEEDBACK_ANALYZER_RATIOSETAGGREGATOR_H
#define USERFEEDBACK_ANALYZER_RATIOSETAGGREGATOR_H
#include "aggregator.h"
#include <memory>
namespace UserFeedback {
namespace Analyzer {
class RatioSetAggregationModel;
class RatioSetAggregator : public Aggregator
{
public: