complete chart view window with option to select chart from thermo columns
This commit is contained in:
@ -13,18 +13,95 @@
|
||||
|
||||
#include "chartviewer.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineSeries>
|
||||
#include <QSettings>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace QtCharts;
|
||||
|
||||
ChartViewer::ChartViewer(QWidget *parent) :
|
||||
QChartView(parent), last_step(-1), chart(new QChart), series(new QLineSeries),
|
||||
ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), active_chart(-1),
|
||||
filename(_filename)
|
||||
{
|
||||
auto *top = new QHBoxLayout;
|
||||
menu->addMenu(file);
|
||||
menu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
||||
|
||||
columns = new QComboBox;
|
||||
top->addWidget(menu);
|
||||
top->addWidget(columns);
|
||||
saveAsAct = file->addAction("&Save Graph As...", this, &ChartWindow::saveAs);
|
||||
closeAct = file->addAction("&Close", this, &QWidget::close);
|
||||
auto *layout = new QVBoxLayout;
|
||||
layout->addLayout(top);
|
||||
setLayout(layout);
|
||||
|
||||
connect(columns, SIGNAL(currentIndexChanged(int)), this, SLOT(change_chart(int)));
|
||||
QSettings settings;
|
||||
resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt());
|
||||
}
|
||||
|
||||
void ChartWindow::add_chart(const QString &title, int index)
|
||||
{
|
||||
auto *chart = new ChartViewer(title, index);
|
||||
layout()->addWidget(chart);
|
||||
columns->addItem(title, index);
|
||||
columns->show();
|
||||
// hide all but the first chart added
|
||||
if (charts.size() > 0) chart->hide();
|
||||
charts.append(chart);
|
||||
active_chart = 0;
|
||||
}
|
||||
|
||||
void ChartWindow::add_data(int step, double data, int index)
|
||||
{
|
||||
for (auto &c : charts)
|
||||
if (c->get_index() == index) c->add_data(step, data);
|
||||
}
|
||||
|
||||
void ChartWindow::saveAs()
|
||||
{
|
||||
if (charts.empty() || (active_chart < 0)) return;
|
||||
QString defaultname = filename + "." + columns->currentText() + ".png";
|
||||
if (filename.isEmpty()) defaultname = columns->currentText() + ".png";
|
||||
QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as Image", defaultname,
|
||||
"Image Files (*.jpg *.png *.bmp *.ppm)");
|
||||
if (!fileName.isEmpty()) {
|
||||
charts[active_chart]->grab().save(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void ChartWindow::change_chart(int index)
|
||||
{
|
||||
int choice = columns->currentData().toInt();
|
||||
for (auto &c : charts) {
|
||||
if (choice == c->get_index())
|
||||
c->show();
|
||||
else
|
||||
c->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void ChartWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QSettings settings;
|
||||
if (!isMaximized()) {
|
||||
settings.setValue("chartx", width());
|
||||
settings.setValue("charty", height());
|
||||
}
|
||||
QWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) :
|
||||
QChartView(parent), last_step(-1), index(_index), chart(new QChart), series(new QLineSeries),
|
||||
xaxis(new QValueAxis), yaxis(new QValueAxis)
|
||||
{
|
||||
chart->legend()->hide();
|
||||
chart->addAxis(xaxis,Qt::AlignBottom);
|
||||
chart->addAxis(yaxis,Qt::AlignLeft);
|
||||
chart->addAxis(xaxis, Qt::AlignBottom);
|
||||
chart->addAxis(yaxis, Qt::AlignLeft);
|
||||
chart->addSeries(series);
|
||||
series->attachAxis(xaxis);
|
||||
series->attachAxis(yaxis);
|
||||
@ -33,22 +110,17 @@ ChartViewer::ChartViewer(QWidget *parent) :
|
||||
yaxis->setTickCount(5);
|
||||
xaxis->setMinorTickCount(5);
|
||||
yaxis->setMinorTickCount(5);
|
||||
yaxis->setTitleText(title);
|
||||
series->setName(title);
|
||||
|
||||
setRenderHint(QPainter::Antialiasing);
|
||||
setChart(chart);
|
||||
setRubberBand(QChartView::RectangleRubberBand);
|
||||
|
||||
QSettings settings;
|
||||
resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt());
|
||||
}
|
||||
|
||||
void ChartViewer::add_column(const QString &title)
|
||||
{
|
||||
yaxis->setTitleText(title);
|
||||
series->setName(title);
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void ChartViewer::add_data(int step, int column, double data)
|
||||
void ChartViewer::add_data(int step, double data)
|
||||
{
|
||||
if (last_step < step) {
|
||||
last_step = step;
|
||||
@ -70,16 +142,6 @@ void ChartViewer::add_data(int step, int column, double data)
|
||||
}
|
||||
}
|
||||
|
||||
void ChartViewer::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QSettings settings;
|
||||
if (!isMaximized()) {
|
||||
settings.setValue("chartx", width());
|
||||
settings.setValue("charty", height());
|
||||
}
|
||||
QChartView::closeEvent(event);
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// c-basic-offset: 4
|
||||
// End:
|
||||
|
||||
@ -14,23 +14,61 @@
|
||||
#ifndef CHARTVIEWER_H
|
||||
#define CHARTVIEWER_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QtCharts>
|
||||
|
||||
class ChartViewer : public QtCharts::QChartView {
|
||||
class QAction;
|
||||
class QMenuBar;
|
||||
class QMenu;
|
||||
class QComboBox;
|
||||
class ChartViewer;
|
||||
|
||||
class ChartWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ChartViewer(QWidget *parent = nullptr);
|
||||
bool has_columns() const { return last_step >= 0; }
|
||||
void add_column(const QString &title);
|
||||
void add_data(int step, int column, double data);
|
||||
int get_last_step() const;
|
||||
ChartWindow(const QString &filename, QWidget *parent = nullptr);
|
||||
|
||||
bool has_charts() const { return !charts.isEmpty(); }
|
||||
void add_chart(const QString &title, int index);
|
||||
void add_data(int step, double data, int index);
|
||||
|
||||
private slots:
|
||||
void saveAs();
|
||||
void change_chart(int index);
|
||||
|
||||
// void normalSize();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private:
|
||||
int last_step;
|
||||
QMenuBar *menu;
|
||||
QMenu *file;
|
||||
QComboBox *columns;
|
||||
QAction *saveAsAct;
|
||||
QAction *closeAct;
|
||||
|
||||
QString filename;
|
||||
int active_chart;
|
||||
QList<ChartViewer *> charts;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
class ChartViewer : public QtCharts::QChartView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ChartViewer(const QString &title, int index, QWidget *parent = nullptr);
|
||||
|
||||
void add_data(int step, double data);
|
||||
int get_index() const { return index; };
|
||||
|
||||
private:
|
||||
int last_step, index;
|
||||
QtCharts::QChart *chart;
|
||||
QtCharts::QLineSeries *series;
|
||||
QtCharts::QValueAxis *xaxis;
|
||||
|
||||
@ -414,15 +414,26 @@ void LammpsGui::logupdate()
|
||||
else
|
||||
step = (int)*(int64_t *)ptr;
|
||||
int ncols = *(int *)lammps.last_thermo("num", 0);
|
||||
if (!chartwindow->has_columns()) {
|
||||
// for (int i = 0; i < ncols; ++i) {
|
||||
chartwindow->add_column((const char *)lammps.last_thermo("keyword", 1));
|
||||
// }
|
||||
if (!chartwindow->has_charts()) {
|
||||
for (int i = 0; i < ncols; ++i) {
|
||||
QString label = (const char *)lammps.last_thermo("keyword", i);
|
||||
// no need to store the timestep column
|
||||
if (label == "Step") continue;
|
||||
chartwindow->add_chart(label, i);
|
||||
}
|
||||
}
|
||||
|
||||
// for (int i = 0; i < ncols; ++i) {
|
||||
chartwindow->add_data(step, 0, *(double *)lammps.last_thermo("data", 1));
|
||||
// }
|
||||
for (int i = 0; i < ncols; ++i) {
|
||||
int datatype = *(int *)lammps.last_thermo("type", i);
|
||||
double data;
|
||||
if (datatype == 0) // int
|
||||
data = *(int *)lammps.last_thermo("data", i);
|
||||
else if (datatype == 2) // double
|
||||
data = *(double *)lammps.last_thermo("data", i);
|
||||
else if (datatype == 4) // bigint
|
||||
data = (double)*(int64_t *)lammps.last_thermo("data", i);
|
||||
chartwindow->add_data(step, data, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -458,18 +469,26 @@ void LammpsGui::run_done()
|
||||
else
|
||||
step = (int)*(int64_t *)ptr;
|
||||
int ncols = *(int *)lammps.last_thermo("num", 0);
|
||||
if (!chartwindow->has_columns()) {
|
||||
// for (int i = 0; i < ncols; ++i) {
|
||||
chartwindow->add_column((const char *)lammps.last_thermo("keyword", 1));
|
||||
// }
|
||||
for (int i = 0; i < ncols; ++i) {
|
||||
if (!chartwindow->has_charts()) {
|
||||
QString label = (const char *)lammps.last_thermo("keyword", i);
|
||||
// no need to store the timestep column
|
||||
if (label == "Step") continue;
|
||||
chartwindow->add_chart(label, i);
|
||||
}
|
||||
int datatype = *(int *)lammps.last_thermo("type", i);
|
||||
double data;
|
||||
if (datatype == 0) // int
|
||||
data = *(int *)lammps.last_thermo("data", i);
|
||||
else if (datatype == 2) // double
|
||||
data = *(double *)lammps.last_thermo("data", i);
|
||||
else if (datatype == 4) // bigint
|
||||
data = (double)*(int64_t *)lammps.last_thermo("data", i);
|
||||
chartwindow->add_data(step, data, i);
|
||||
}
|
||||
|
||||
// for (int i = 0; i < ncols; ++i) {
|
||||
chartwindow->add_data(step, 0, *(double *)lammps.last_thermo("data", 1));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool success = true;
|
||||
constexpr int BUFLEN = 1024;
|
||||
char errorbuf[BUFLEN];
|
||||
@ -552,13 +571,13 @@ void LammpsGui::run_buffer()
|
||||
|
||||
// if configured, delete old log window before opening new one
|
||||
if (settings.value("chartreplace", false).toBool()) delete chartwindow;
|
||||
chartwindow = new ChartViewer();
|
||||
chartwindow = new ChartWindow(current_file);
|
||||
chartwindow->setWindowTitle("LAMMPS-GUI - Thermo charts from running LAMMPS on buffer - " +
|
||||
current_file);
|
||||
chartwindow->setWindowIcon(QIcon(":/lammps-icon-128x128.png"));
|
||||
chartwindow->setMinimumSize(400, 300);
|
||||
shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), chartwindow);
|
||||
QObject::connect(shortcut, &QShortcut::activated, chartwindow, &ChartViewer::close);
|
||||
QObject::connect(shortcut, &QShortcut::activated, chartwindow, &ChartWindow::close);
|
||||
shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Slash), chartwindow);
|
||||
QObject::connect(shortcut, &QShortcut::activated, this, &LammpsGui::stop_run);
|
||||
chartwindow->show();
|
||||
|
||||
@ -39,7 +39,7 @@ class Highlighter;
|
||||
class StdCapture;
|
||||
class Preferences;
|
||||
class ImageViewer;
|
||||
class ChartViewer;
|
||||
class ChartWindow;
|
||||
|
||||
class LammpsGui : public QMainWindow {
|
||||
Q_OBJECT
|
||||
@ -86,7 +86,7 @@ private:
|
||||
QLabel *status;
|
||||
QPlainTextEdit *logwindow;
|
||||
ImageViewer *imagewindow;
|
||||
ChartViewer *chartwindow;
|
||||
ChartWindow *chartwindow;
|
||||
QTimer *logupdater;
|
||||
QLabel *dirstatus;
|
||||
QProgressBar *progress;
|
||||
|
||||
Reference in New Issue
Block a user