Extending script plot() function
This commit is contained in:
@@ -30,6 +30,7 @@ add_subdirectory(libXISF)
|
|||||||
set(TENMON_SRC
|
set(TENMON_SRC
|
||||||
about.cpp about.h
|
about.cpp about.h
|
||||||
batchprocessing.cpp batchprocessing.h batchprocessing.ui
|
batchprocessing.cpp batchprocessing.h batchprocessing.ui
|
||||||
|
chartgraph.h chartgraph.cpp
|
||||||
database.cpp database.h
|
database.cpp database.h
|
||||||
databaseview.cpp databaseview.h
|
databaseview.cpp databaseview.h
|
||||||
delete.cpp
|
delete.cpp
|
||||||
|
|||||||
+4
-24
@@ -14,6 +14,7 @@
|
|||||||
#include <QChartView>
|
#include <QChartView>
|
||||||
#include <QLineSeries>
|
#include <QLineSeries>
|
||||||
#include "scriptengine.h"
|
#include "scriptengine.h"
|
||||||
|
#include "chartgraph.h"
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
@@ -271,31 +272,10 @@ QJSValue BatchProcessing::getItem(const QStringList &items, const QString &label
|
|||||||
return ok ? ret : QJSValue();
|
return ok ? ret : QJSValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BatchProcessing::plot(const QVector<QPointF> &points)
|
void BatchProcessing::plot(const QVariant &graph)
|
||||||
{
|
{
|
||||||
QDialog *diag = new QDialog(this);
|
ChartGraph *chart = new ChartGraph(this);
|
||||||
diag->setAttribute(Qt::WA_DeleteOnClose);
|
chart->plot(graph);
|
||||||
diag->setModal(false);
|
|
||||||
diag->setWindowTitle(tr("Chart"));
|
|
||||||
|
|
||||||
QChartView *chartView = new QChartView(diag);
|
|
||||||
diag->setLayout(new QVBoxLayout);
|
|
||||||
diag->layout()->addWidget(chartView);
|
|
||||||
|
|
||||||
QChart *chart = new QChart;
|
|
||||||
chart->setParent(chartView);
|
|
||||||
|
|
||||||
auto series = new QLineSeries(chartView);
|
|
||||||
series->append(points);
|
|
||||||
chart->addSeries(series);
|
|
||||||
chart->createDefaultAxes();
|
|
||||||
chart->setTitle("Simple line graph");
|
|
||||||
chart->legend()->hide();
|
|
||||||
|
|
||||||
chartView->setChart(chart);
|
|
||||||
chartView->setRenderHint(QPainter::Antialiasing);
|
|
||||||
diag->resize(640, 480);
|
|
||||||
diag->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void openDir(const QString &path)
|
void openDir(const QString &path)
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ public slots:
|
|||||||
QJSValue getFloat(const QString &label, double value, int decimals);
|
QJSValue getFloat(const QString &label, double value, int decimals);
|
||||||
QJSValue getItem(const QStringList &items, const QString &label, int current);
|
QJSValue getItem(const QStringList &items, const QString &label, int current);
|
||||||
|
|
||||||
void plot(const QVector<QPointF> &points);
|
void plot(const QVariant &graph);
|
||||||
};
|
};
|
||||||
|
|
||||||
void openDir(const QString &path);
|
void openDir(const QString &path);
|
||||||
|
|||||||
+238
@@ -0,0 +1,238 @@
|
|||||||
|
#include "chartgraph.h"
|
||||||
|
#include <QChartView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLineSeries>
|
||||||
|
#include <QBarSeries>
|
||||||
|
#include <QBarSet>
|
||||||
|
#include <QScatterSeries>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QValueAxis>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
class ChartView : public QChartView
|
||||||
|
{
|
||||||
|
QPointF _mousePos;
|
||||||
|
bool _scroll = false;
|
||||||
|
public:
|
||||||
|
ChartView(QWidget *parent) : QChartView(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *event) override
|
||||||
|
{
|
||||||
|
switch(event->key())
|
||||||
|
{
|
||||||
|
case Qt::Key_Plus:
|
||||||
|
chart()->zoomIn();
|
||||||
|
break;
|
||||||
|
case Qt::Key_Minus:
|
||||||
|
chart()->zoomOut();
|
||||||
|
break;
|
||||||
|
case Qt::Key_Left:
|
||||||
|
chart()->scroll(-10, 0);
|
||||||
|
break;
|
||||||
|
case Qt::Key_Right:
|
||||||
|
chart()->scroll(10, 0);
|
||||||
|
break;
|
||||||
|
case Qt::Key_Up:
|
||||||
|
chart()->scroll(0, 10);
|
||||||
|
break;
|
||||||
|
case Qt::Key_Down:
|
||||||
|
chart()->scroll(0, -10);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
QGraphicsView::keyPressEvent(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void mousePressEvent(QMouseEvent *event) override
|
||||||
|
{
|
||||||
|
if(event->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
_scroll = true;
|
||||||
|
_mousePos = event->position();
|
||||||
|
}
|
||||||
|
|
||||||
|
QChartView::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override
|
||||||
|
{
|
||||||
|
if(_scroll)
|
||||||
|
{
|
||||||
|
QPointF pos = event->position();
|
||||||
|
chart()->scroll(_mousePos.x() - pos.x(), pos.y() - _mousePos.y());
|
||||||
|
_mousePos = pos;
|
||||||
|
}
|
||||||
|
QChartView::mouseMoveEvent(event);
|
||||||
|
}
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override
|
||||||
|
{
|
||||||
|
_scroll = false;
|
||||||
|
QChartView::mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ChartGraph::ChartGraph(QWidget *parent) : QDialog(parent)
|
||||||
|
{
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
setModal(false);
|
||||||
|
|
||||||
|
_chartView = new ChartView(this);
|
||||||
|
setLayout(new QVBoxLayout);
|
||||||
|
layout()->addWidget(_chartView);
|
||||||
|
|
||||||
|
_chart = new QChart;
|
||||||
|
_chartView->setChart(_chart);
|
||||||
|
_chartView->setRenderHint(QPainter::Antialiasing);
|
||||||
|
resize(1024, 768);
|
||||||
|
|
||||||
|
QMenuBar *menuBar = new QMenuBar(this);
|
||||||
|
menuBar->addAction(tr("Save"), this, &ChartGraph::save);
|
||||||
|
layout()->setMenuBar(menuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChartGraph::plot(const QVariant &graph)
|
||||||
|
{
|
||||||
|
QVariantMap map = graph.toMap();
|
||||||
|
|
||||||
|
_chart->setTitle(map["title"].toString());
|
||||||
|
if(map.contains("legend"))
|
||||||
|
{
|
||||||
|
QVariantMap legend = map["legend"].toMap();
|
||||||
|
if(legend.contains("visible"))
|
||||||
|
_chart->legend()->setVisible(legend["visible"].toBool());
|
||||||
|
|
||||||
|
QString align = legend["align"].toString();
|
||||||
|
if(align == "top")
|
||||||
|
_chart->legend()->setAlignment(Qt::AlignTop);
|
||||||
|
else if(align == "left")
|
||||||
|
_chart->legend()->setAlignment(Qt::AlignLeft);
|
||||||
|
else if(align == "bottom")
|
||||||
|
_chart->legend()->setAlignment(Qt::AlignBottom);
|
||||||
|
else if(align == "right")
|
||||||
|
_chart->legend()->setAlignment(Qt::AlignRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
QBarSeries *barSeries = nullptr;
|
||||||
|
|
||||||
|
qreal minY = INFINITY;
|
||||||
|
qreal maxY = -INFINITY;
|
||||||
|
|
||||||
|
for(auto s : map["series"].toList())
|
||||||
|
{
|
||||||
|
QVariantMap serie = s.toMap();
|
||||||
|
QString type = serie["type"].toString();
|
||||||
|
if(type == "line" || type == "points" || type == "linePoints" || type.isEmpty())
|
||||||
|
{
|
||||||
|
QXYSeries *series = nullptr;
|
||||||
|
if(type == "points")
|
||||||
|
{
|
||||||
|
QScatterSeries *scatter = new QScatterSeries(_chart);
|
||||||
|
series = scatter;
|
||||||
|
QString shape = serie["shape"].toString();
|
||||||
|
if(shape == "circle")scatter->setMarkerShape(QScatterSeries::MarkerShapeCircle);
|
||||||
|
else if(shape == "rectangle")scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
|
||||||
|
else if(shape == "triangle")scatter->setMarkerShape(QScatterSeries::MarkerShapeTriangle);
|
||||||
|
else if(shape == "star")scatter->setMarkerShape(QScatterSeries::MarkerShapeStar);
|
||||||
|
else if(shape == "pentagon")scatter->setMarkerShape(QScatterSeries::MarkerShapePentagon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
series = new QLineSeries(_chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
series->setName(serie["title"].toString());
|
||||||
|
QVariantList x = serie["x"].toList();
|
||||||
|
QVariantList y = serie["y"].toList();
|
||||||
|
if(x.isEmpty())
|
||||||
|
{
|
||||||
|
for(int i = 0; i < y.size(); i++)
|
||||||
|
{
|
||||||
|
qreal val = y[i].toDouble();
|
||||||
|
minY = std::min(minY, val);
|
||||||
|
maxY = std::max(maxY, val);
|
||||||
|
series->append(i, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int size = std::min(x.size(), y.size());
|
||||||
|
for(int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
qreal val = y[i].toDouble();
|
||||||
|
minY = std::min(minY, val);
|
||||||
|
maxY = std::max(maxY, val);
|
||||||
|
series->append(x[i].toDouble(), val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_chart->addSeries(series);
|
||||||
|
if(serie["bestFit"].toBool())
|
||||||
|
{
|
||||||
|
series->setBestFitLineVisible(true);
|
||||||
|
QPen pen = series->bestFitLinePen();
|
||||||
|
pen.setColor(series->color());
|
||||||
|
pen.setStyle(Qt::DashLine);
|
||||||
|
series->setBestFitLinePen(pen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == "linePoints")
|
||||||
|
series->setPointsVisible(true);
|
||||||
|
|
||||||
|
if(serie.contains("color"))
|
||||||
|
{
|
||||||
|
QString color = serie["color"].toString();
|
||||||
|
if(QColor::isValidColorName(color))series->setColor(QColor::fromString(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == "bar")
|
||||||
|
{
|
||||||
|
if(!barSeries)
|
||||||
|
{
|
||||||
|
barSeries = new QBarSeries(_chart);
|
||||||
|
_chart->addSeries(barSeries);
|
||||||
|
}
|
||||||
|
QBarSet *set = new QBarSet(serie["title"].toString());
|
||||||
|
QVariantList y = serie["y"].toList();
|
||||||
|
for(int i = 0; i < y.size(); i++)
|
||||||
|
{
|
||||||
|
qreal val = y[i].toDouble();
|
||||||
|
minY = std::min(minY, val);
|
||||||
|
maxY = std::max(maxY, val);
|
||||||
|
set->append(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
barSeries->append(set);
|
||||||
|
if(serie.contains("color"))
|
||||||
|
{
|
||||||
|
QString color = serie["color"].toString();
|
||||||
|
if(QColor::isValidColorName(color))set->setColor(QColor::fromString(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_chart->createDefaultAxes();
|
||||||
|
QValueAxis *yaxis = qobject_cast<QValueAxis*>(_chart->axes(Qt::Vertical).front());
|
||||||
|
if(yaxis)
|
||||||
|
{
|
||||||
|
qreal off = (maxY - minY) * 0.05;
|
||||||
|
yaxis->setRange(std::min(minY - off, 0.0), maxY + off);
|
||||||
|
}
|
||||||
|
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChartGraph::save()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
QString dir = settings.value("mainwindow/lastdir").toString();
|
||||||
|
QString output = QFileDialog::getSaveFileName(this, tr("Save as"), dir, "PNG (*.png)");
|
||||||
|
|
||||||
|
if(!output.isEmpty())
|
||||||
|
{
|
||||||
|
QPixmap graph = _chartView->grab();
|
||||||
|
graph.toImage().save(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef CHARTGRAPH_H
|
||||||
|
#define CHARTGRAPH_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QJSValue>
|
||||||
|
#include <QChart>
|
||||||
|
|
||||||
|
class ChartView;
|
||||||
|
|
||||||
|
class ChartGraph : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QChart *_chart;
|
||||||
|
ChartView *_chartView;
|
||||||
|
public:
|
||||||
|
explicit ChartGraph(QWidget *parent = nullptr);
|
||||||
|
void plot(const QVariant &graph);
|
||||||
|
public slots:
|
||||||
|
void save();
|
||||||
|
signals:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHARTGRAPH_H
|
||||||
+6
-12
@@ -136,19 +136,13 @@ QJSValue ScriptEngine::getItem(const QStringList &items, const QString &label, i
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::plot(const QJSValue &pointsArray)
|
void ScriptEngine::plot(const QJSValue &graph)
|
||||||
{
|
{
|
||||||
if(pointsArray.isArray())
|
QVariant graphV = graph.toVariant(QJSValue::ConvertJSObjects);
|
||||||
{
|
if(graphV.isValid())
|
||||||
int len = pointsArray.property("length").toInt();
|
QMetaObject::invokeMethod(_parent, "plot", Qt::QueuedConnection, Q_ARG(QVariant, graphV));
|
||||||
QVector<QPointF> points;
|
else
|
||||||
for(int i = 0; i < len; i++)
|
logError("Invalid value to be plotted");
|
||||||
{
|
|
||||||
QJSValue point = pointsArray.property(i);
|
|
||||||
points.append(QPointF(point.property("x").toNumber(), point.property("y").toNumber()));
|
|
||||||
}
|
|
||||||
QMetaObject::invokeMethod(_parent, "plot", Qt::QueuedConnection, Q_ARG(QVector<QPointF>, points));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJSValue ScriptEngine::openFile(const QString &fileName, const QString &mode)
|
QJSValue ScriptEngine::openFile(const QString &fileName, const QString &mode)
|
||||||
|
|||||||
Reference in New Issue
Block a user