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"),
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)),
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() {
}
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())
|| 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();
}
}
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);
+}
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();
void settings_widget_accepted();
void finished_cell(int num);
void finished();
+ void load_json();
+ void save_json();
};
#endif // BIGINTWIDGET_H
// mandel.cpp
+#include <QFile>
+#include <QJsonArray>
+#include <QJsonDocument>
+
#include "colors.h"
#include "mandel.h"
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);
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, ¤t);
-}
-
-void MandelSettings::set_max_iter(size_t max_iter) {
- current.set_max_iter(max_iter);
+ setup_cells(cells, ¶ms);
}
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);
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, ¤t);
+ setup_cells(cells, ¶ms);
+}
+
+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(¶ms));
+ 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) {}
}
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();
}
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;
+}
#ifndef MANDEL_H
#define MANDEL_H
+#include <QJsonObject>
#include <QPixmap>
#include <QPoint>
#include <QVector>
};
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 {
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;
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);
this->result = result;
}
MandelResultCell iterate() const;
+ MandelResultCell from_json(const QJsonObject &json);
+ QJsonObject to_json() const;
};
#endif // MANDEL_H
#include "settingswidget.h"
-
SettingsWidget::SettingsWidget(QWidget *parent)
: QDialog(parent),
max_iter(new QLineEdit("", this)),