]> git.mar77i.info Git - bigintmandel/commitdiff
save and load calculations as json
authormar77i <mar77i@protonmail.ch>
Sun, 21 Apr 2024 23:16:30 +0000 (01:16 +0200)
committermar77i <mar77i@protonmail.ch>
Sun, 21 Apr 2024 23:31:00 +0000 (01:31 +0200)
bigintwidget.cpp
bigintwidget.h
mandel.cpp
mandel.h
settingswidget.cpp

index d4289a110c428db4abcffc4189f647b726aa57ee..30c7ff2cc3c582e4feaef60b485383414bf7f5ce 100644 (file)
@@ -20,6 +20,18 @@ static inline QMenuBar *setup_menu_bar(BigintWidget *parent) {
         parent,
         &BigintWidget::reset
     );
+    QObject::connect(
+        menu->addAction("&Load"),
+        &QAction::triggered,
+        parent,
+        &BigintWidget::load_json
+    );
+    QObject::connect(
+        menu->addAction("&Save"),
+        &QAction::triggered,
+        parent,
+        &BigintWidget::save_json
+    );
     menu->addSeparator();
     QObject::connect(
         menu->addAction("&Export"),
@@ -45,6 +57,17 @@ static inline QMenuBar *setup_menu_bar(BigintWidget *parent) {
     return menu_bar;
 }
 
+static inline void start_calculation(
+    QFutureWatcher<MandelResultCell> *fw, QVector<MandelCell> cells
+) {
+    fw->setFuture(
+        QtConcurrent::mapped(
+            cells,
+            [](const MandelCell &cell){ return cell.iterate(); }
+        )
+    );
+}
+
 BigintWidget::BigintWidget(QWidget *parent)
 :   QWidget(parent),
     fw(new QFutureWatcher<MandelResultCell>(this)),
@@ -74,15 +97,13 @@ BigintWidget::BigintWidget(QWidget *parent)
         this,
         &BigintWidget::finished
     );
-    fw->setFuture(
-        QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
-    );
+    start_calculation(fw, settings.get_cells());
     setLayout(new QVBoxLayout());
     layout()->addWidget(setup_menu_bar(this));
     layout()->addWidget(scroll_area);
     status_bar->setSizeGripEnabled(false);
     layout()->addWidget(status_bar);
-    img_label->setMinimumSize(settings.get_current().get_size());
+    img_label->resize(settings.get_params().get_size());
 }
 
 BigintWidget::~BigintWidget() {
@@ -132,7 +153,7 @@ void BigintWidget::paintEvent(QPaintEvent *event) {
 }
 
 void BigintWidget::mousePressEvent(QMouseEvent *event) {
-    QSize size(settings.get_current().get_size());
+    QSize size(settings.get_params().get_size());
     QPoint pos(event->pos());
     QWidget *w;
     for (w = img_label; w != this; w = w->parentWidget())
@@ -144,10 +165,8 @@ void BigintWidget::mousePressEvent(QMouseEvent *event) {
             || pos.y() < 0
             || pos.y() >= size.height())
         return;
-    settings.zoom(scroll_area->viewport()->size(), pos);
-    fw->setFuture(
-        QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
-    );
+    settings.zoom(get_ideal_size(), pos);
+    start_calculation(fw, settings.get_cells());
     update_img();
 }
 
@@ -157,33 +176,46 @@ void BigintWidget::update_img() {
 }
 
 void BigintWidget::export_img() {
-    QString filename = QFileDialog::getSaveFileName(
+    QString file_name = QFileDialog::getSaveFileName(
         this, "Save image", "", "Images (*.png *.xpm *.jpg)"
     );
-    if (!filename.isEmpty())
-        settings.save_img(filename);
+    if (!file_name.isEmpty())
+        settings.save_img(file_name);
 }
 
 void BigintWidget::exec_settings_widget() {
-    settings_widget->update_fields(settings.get_current(), fw->isFinished());
+    settings_widget->update_fields(settings.get_params(), fw->isFinished());
     settings_widget->exec();
 }
 
 void BigintWidget::reset() {
-    QSize size(scroll_area->viewport()->size());
     fw->cancel();
     fw->waitForFinished();
-    settings.reset(128, size);
-    fw->setFuture(
-        QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
-    );
+    settings.reset(128, get_ideal_size());
+    start_calculation(fw, settings.get_cells());
     update_img();
 }
 
 void BigintWidget::settings_widget_accepted() {
     settings.set_max_iter(settings_widget->get_max_iter().toULongLong());
-    fw->setFuture(
-        QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
-    );
+    start_calculation(fw, settings.get_cells());
     update_img();
 }
+
+void BigintWidget::load_json() {
+    QString file_name = QFileDialog::getOpenFileName(
+        this, "Load JSON", "", "JSON Documents (*.json)"
+    );
+    if (!file_name.isEmpty()) {
+        settings.load_json(file_name);
+        update_img();
+    }
+}
+
+void BigintWidget::save_json() {
+    QString file_name = QFileDialog::getSaveFileName(
+        this, "Save JSON", "", "JSON Documents (*.json)"
+    );
+    if (!file_name.isEmpty())
+        settings.save_json(file_name);
+}
index 6db7f5c6999050962544207a98641d4bf4cbc1ba..705be1814245dd59b611d6bc3d8f21382d8900a5 100644 (file)
@@ -25,6 +25,10 @@ class BigintWidget : public QWidget {
     QStatusBar *status_bar;
     SettingsWidget *settings_widget;
 
+    inline const QSize get_ideal_size() const {
+        return scroll_area->size().shrunkBy(scroll_area->contentsMargins());
+    }
+
 public:
     BigintWidget(QWidget *parent = nullptr);
     ~BigintWidget();
@@ -39,6 +43,8 @@ public Q_SLOT:
     void settings_widget_accepted();
     void finished_cell(int num);
     void finished();
+    void load_json();
+    void save_json();
 };
 
 #endif // BIGINTWIDGET_H
index 70910d35d434b58ce43e9f9842607257128fd45e..f68b5ffd1aaf51df5949df534074ee39f91ea7d5 100644 (file)
@@ -1,6 +1,10 @@
 
 // mandel.cpp
 
+#include <QFile>
+#include <QJsonArray>
+#include <QJsonDocument>
+
 #include "colors.h"
 #include "mandel.h"
 
@@ -32,6 +36,28 @@ MandelParams::MandelParams(const MandelParams &other)
     center_f(other.center_f),
     one(other.one) {}
 
+MandelParams MandelParams::from_json(const QJsonObject &json) {
+    return MandelParams(
+        json["max_iter"].toString().toULongLong(),
+        QSize(json["size_w"].toInt(), json["size_h"].toInt()),
+        MpzPoint(
+            mpz_class(json["center_f_x"].toString().toStdString()),
+            mpz_class(json["center_f_y"].toString().toStdString())
+        ),
+        mpz_class(json["one"].toString().toStdString())
+    );
+}
+
+QJsonObject MandelParams::to_json() const {
+    QJsonObject json;
+    json["max_iter"] = QString::number(max_iter);
+    json["size_w"] = size.width();
+    json["size_h"] = size.height();
+    json["center_f_x"] = QString::fromStdString(center_f.get_x().get_str());
+    json["center_f_y"] = QString::fromStdString(center_f.get_y().get_str());
+    json["one"] = QString::fromStdString(one.get_str());
+    return json;
+}
 
 static inline void incrpos(QPoint &pos, const int width) {
     pos.setX(pos.x() + 1);
@@ -70,21 +96,15 @@ MandelSettings::MandelSettings(size_t max_iter, const QSize size)
 
 void MandelSettings::zoom(const QSize size, const QPoint pos) {
     MpzPoint p = cells[img->width() * pos.y() + pos.x()].get_rpos0();
-    bool resize_img = size != current.get_size();
-    current = MandelParams(
-        current.get_max_iter(),
+    params = MandelParams(
+        params.get_max_iter(),
         size,
         MpzPoint(p.get_x() * 2, p.get_y() * 2),
-        current.get_one() * 2
+        params.get_one() * 2
     );
-    if (resize_img)
-        img = setup_image(img, size);
+    img = setup_image(img, size);
     img->fill(Qt::GlobalColor::black);
-    setup_cells(cells, &current);
-}
-
-void MandelSettings::set_max_iter(size_t max_iter) {
-    current.set_max_iter(max_iter);
+    setup_cells(cells, &params);
 }
 
 void MandelSettings::finished_cell(int num, const MandelResultCell &result) {
@@ -95,10 +115,6 @@ void MandelSettings::finished_cell(int num, const MandelResultCell &result) {
     img->setPixelColor(cells[num].get_pos(), cells[num].get_color());
 }
 
-MandelResultCell MandelSettings::iterate(const MandelCell &cell) {
-    return cell.iterate();
-}
-
 void MandelSettings::save_img(QString file_name) {
     if (img)
         img->save(file_name);
@@ -116,9 +132,45 @@ void MandelSettings::reset(size_t max_iter, const QSize size) {
     ione |= ione >> 16;
     one = mpz_class(ione + 1);
     center_f = MpzPoint(one * -3 / 4, 0);
-    current = MandelParams(max_iter, size, center_f, one);
+    params = MandelParams(max_iter, size, center_f, one);
     img = setup_image(img, size);
-    setup_cells(cells, &current);
+    setup_cells(cells, &params);
+}
+
+void MandelSettings::load_json(QString file_name) {
+    QFile file(file_name);
+    QJsonObject json;
+    QJsonArray json_array;
+    int i;
+    if (!file.open(QIODevice::ReadOnly)) {
+        qWarning("Couldn't open save file.");
+        return;
+    }
+    json = QJsonDocument::fromJson(file.readAll()).object();
+    params = MandelParams::from_json(json["params"].toObject());
+    json_array = json["cells"].toArray();
+    cells.resize(json_array.size(), MandelCell(&params));
+    img = setup_image(img, params.get_size());
+    for (i = 0; i < json_array.size(); i++)
+        finished_cell(i, cells[i].from_json(json_array[i].toObject()));
+    file.close();
+}
+
+void MandelSettings::save_json(QString file_name) {
+    QVector<MandelCell>::iterator i;
+    QFile file(file_name);
+    QJsonObject json;
+    QJsonArray c;
+    json["params"] = params.to_json();
+    for (i = cells.begin(); i != cells.end(); i++)
+        c.append(i->to_json());
+    json["cells"] = c;
+    if (!file.open(QIODevice::WriteOnly)) {
+        qWarning("Couldn't open save file.");
+        return;
+    }
+    file.write(QJsonDocument(json).toJson());
+    file.close();
 }
 
 MandelCell::MandelCell(const MandelParams *params) : params(params) {}
@@ -139,10 +191,10 @@ void MandelCell::setup(const QPoint pos) {
 }
 
 MandelResultCell MandelCell::iterate() const {
-    MpzPoint rpos = result.rpos, sq;
+    MpzPoint rpos = result.get_rpos(), sq;
     mpz_class one = params->get_one(), four = one * one * 4;
     mpz_class sqx, sqy;
-    size_t iter = result.iter;
+    size_t iter = result.get_iter();
     for (; iter < params->get_max_iter(); iter++) {
         sqx = rpos.get_x() * rpos.get_x();
         sqy = rpos.get_y() * rpos.get_y();
@@ -155,3 +207,31 @@ MandelResultCell MandelCell::iterate() const {
     }
     return MandelResultCell(iter, rpos);
 }
+
+MandelResultCell MandelCell::from_json(const QJsonObject &json) {
+    this->pos = QPoint(json["pos_x"].toInt(), json["pos_y"].toInt());
+    this->rpos0 = MpzPoint(
+        mpz_class(json["rpos0_x"].toString().toStdString()),
+        mpz_class(json["rpos0_y"].toString().toStdString())
+    );
+    return MandelResultCell(
+        json["iter"].toString().toULongLong(),
+        MpzPoint(
+            mpz_class(json["rpos_x"].toString().toStdString()),
+            mpz_class(json["rpos_y"].toString().toStdString())
+        )
+    );
+}
+
+QJsonObject MandelCell::to_json() const {
+    const MpzPoint rpos(result.get_rpos());
+    QJsonObject json;
+    json["pos_x"] = pos.x();
+    json["pos_y"] = pos.y();
+    json["rpos0_x"] = QString::fromStdString(rpos0.get_x().get_str());
+    json["rpos0_y"] = QString::fromStdString(rpos0.get_y().get_str());
+    json["iter"] = QString::number(result.get_iter());
+    json["rpos_x"] = QString::fromStdString(rpos.get_x().get_str());
+    json["rpos_y"] = QString::fromStdString(rpos.get_y().get_str());
+    return json;
+}
index ffb9ff1e50b1f451c11d95911eb43d5edc906213..dba45e3d8b1b6472a6e696f811a9febec94a9df4 100644 (file)
--- a/mandel.h
+++ b/mandel.h
@@ -4,6 +4,7 @@
 #ifndef MANDEL_H
 #define MANDEL_H
 
+#include <QJsonObject>
 #include <QPixmap>
 #include <QPoint>
 #include <QVector>
@@ -22,14 +23,13 @@ public:
 };
 
 class MandelResultCell {
-    friend class MandelCell;
-
     size_t iter;
     MpzPoint rpos;
 public:
     MandelResultCell();
     MandelResultCell(size_t iter, MpzPoint rpos);
     const size_t get_iter() const { return iter; }
+    const MpzPoint get_rpos() const { return rpos; }
 };
 
 class MandelParams {
@@ -48,31 +48,34 @@ public:
         mpz_class one
     );
     MandelParams(const MandelParams &other);
-
     const size_t get_max_iter() const { return max_iter; }
     void set_max_iter(const size_t max_iter) { this->max_iter = max_iter; }
     const QSize get_size() const { return size; }
     const MpzPoint get_center_f() const { return center_f; }
     const mpz_class get_one() const { return one; }
+
+    static MandelParams from_json(const QJsonObject &json);
+    QJsonObject to_json() const;
 };
 
 class MandelSettings {
-    MandelParams current;
+    MandelParams params;
     QImage *img;
     QVector<MandelCell> cells;
 
 public:
     MandelSettings(size_t max_iter, QSize size);
-    const QPixmap get_pixmap() const { return QPixmap::fromImage(*img); }
-    const QVector<MandelCell> get_cells() const { return cells; }
-    const MandelParams get_current() const { return current; }
+    inline const QPixmap get_pixmap() const { return QPixmap::fromImage(*img); }
+    inline const QVector<MandelCell> get_cells() const { return cells; }
+    inline const MandelParams &get_params() const { return params; }
+    inline void set_max_iter(size_t max_iter) { params.set_max_iter(max_iter); }
 
     void zoom(const QSize size, const QPoint pos);
-    void set_max_iter(size_t max_iter);
     void finished_cell(int num, const MandelResultCell &cell);
-    static MandelResultCell iterate(const MandelCell &cell);
     void save_img(QString file_name);
     void reset(size_t max_iter, QSize size);
+    void load_json(QString file_name);
+    void save_json(QString file_name);
 };
 
 extern QVector<QColor> colors;
@@ -85,14 +88,20 @@ class MandelCell {
 
 public:
     MandelCell(const MandelParams *params);
+    MandelCell(
+        const MandelParams *params,
+        const QPoint pos,
+        const MpzPoint rpos0,
+        const MandelResultCell result
+    );
     MandelCell(const MandelCell &cell);
     inline const QPoint get_pos() const { return pos; }
-    inline const size_t get_iter() const { return result.iter; }
     inline const MpzPoint get_rpos0() const { return rpos0; }
     inline const QColor get_color() const {
-        return result.iter < params->get_max_iter()
-        ? colors[result.iter % colors.size()]
-        : Qt::GlobalColor::black;
+        size_t iter = result.get_iter();
+        return iter < params->get_max_iter()
+            ? colors[iter % colors.size()]
+            : Qt::GlobalColor::black;
     }
 
     void setup(const QPoint pos);
@@ -100,6 +109,8 @@ public:
         this->result = result;
     }
     MandelResultCell iterate() const;
+    MandelResultCell from_json(const QJsonObject &json);
+    QJsonObject to_json() const;
 };
 
 #endif // MANDEL_H
index a6d3c6e18d21679a7dd6c2d332b6de1f342bc916..f87086fdca48bbc23784338b031a3c1848ca3743 100644 (file)
@@ -8,7 +8,6 @@
 
 #include "settingswidget.h"
 
-
 SettingsWidget::SettingsWidget(QWidget *parent)
 :   QDialog(parent),
     max_iter(new QLineEdit("", this)),