bigintwidget.h
mandel.cpp
mandel.h
+ settingswidget.cpp
+ settingswidget.h
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
#include <QFileDialog>
#include <QLayout>
#include <QMouseEvent>
-#include <QScrollArea>
+#include <QPushButton>
#include <QtConcurrent/QtConcurrent>
#include "bigintwidget.h"
+static inline QMenuBar *setup_menu_bar(BigintWidget *parent) {
+ QMenuBar *menu_bar = new QMenuBar(parent);
+ QMenu *menu = new QMenu("&File", parent);
+ QPushButton *button = new QPushButton("Settings");
+ menu_bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QObject::connect(
+ menu->addAction("&Reset"),
+ &QAction::triggered,
+ parent,
+ &BigintWidget::reset
+ );
+ menu->addSeparator();
+ QObject::connect(
+ menu->addAction("&Export"),
+ &QAction::triggered,
+ parent,
+ &BigintWidget::export_img
+ );
+ menu->addSeparator();
+ QObject::connect(
+ menu->addAction("E&xit"),
+ &QAction::triggered,
+ parent,
+ &BigintWidget::close
+ );
+ menu_bar->addMenu(menu);
+ QObject::connect(
+ button,
+ &QPushButton::clicked,
+ parent,
+ &BigintWidget::exec_settings_widget
+ );
+ menu_bar->setCornerWidget(button);
+ return menu_bar;
+}
+
BigintWidget::BigintWidget(QWidget *parent)
: QWidget(parent),
fw(new QFutureWatcher<MandelResultCell>(this)),
settings(128, QSize(502, 334)),
+ scroll_area(new QScrollArea(this)),
img_label(new QLabel(this)),
img_dirty(true),
- status_bar(new QStatusBar(this))
+ status_bar(new QStatusBar(this)),
+ settings_widget(new SettingsWidget(this))
{
- QScrollArea *scroll_area = new QScrollArea(this);
scroll_area->setWidget(img_label);
connect(
fw,
this,
&BigintWidget::finished
);
- fw->setFuture(QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate));
+ fw->setFuture(
+ QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
+ );
setLayout(new QVBoxLayout());
- layout()->addWidget(setup_menu_bar());
+ layout()->addWidget(setup_menu_bar(this));
layout()->addWidget(scroll_area);
status_bar->setSizeGripEnabled(false);
layout()->addWidget(status_bar);
- img_label->setMinimumSize(settings.get_size());
+ img_label->setMinimumSize(settings.get_current().get_size());
}
BigintWidget::~BigintWidget() {
fw->waitForFinished();
}
-QMenuBar *BigintWidget::setup_menu_bar() {
- QMenuBar *menu_bar = new QMenuBar(this);
- QMenu *menu = new QMenu("&File", this);
- menu_bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- connect(
- menu->addAction("&Export"),
- &QAction::triggered,
- this,
- &BigintWidget::export_img
- );
- menu->addSeparator();
- connect(
- menu->addAction("E&xit"),
- &QAction::triggered,
- this,
- &BigintWidget::close
- );
- menu_bar->addMenu(menu);
- return menu_bar;
-}
-
void BigintWidget::finished_cell(int num) {
settings.finished_cell(num, fw->resultAt(num));
img_dirty = true;
static int prev_num_threads = -1;
if (img_dirty) {
img_label->setPixmap(settings.get_pixmap());
+ img_label->resize(img_label->pixmap().size());
img_dirty = false;
if (fw->isFinished())
finished_status(status_bar);
void BigintWidget::mousePressEvent(QMouseEvent *event) {
if (!fw->isFinished() || event->button() != Qt::MouseButton::LeftButton)
return;
- QSize size(settings.get_size());
+ QSize size(settings.get_current().get_size());
QPoint pos = img_label->mapFromParent(event->pos());
if (pos.x() < 0 || pos.x() >= size.width()
|| pos.y() < 0 || pos.y() >= size.height())
return;
settings.zoom(pos);
- fw->setFuture(QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate));
+ fw->setFuture(
+ QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
+ );
img_dirty = true;
update();
}
void BigintWidget::export_img() {
- settings.save_img(
- QFileDialog::getSaveFileName(
- this, "Save image", "", "Images (*.png *.xpm *.jpg)"
- )
+ QString filename = QFileDialog::getSaveFileName(
+ this, "Save image", "", "Images (*.png *.xpm *.jpg)"
);
+ if (!filename.isEmpty())
+ settings.save_img(filename);
+}
+
+void BigintWidget::exec_settings_widget() {
+ settings_widget->update_fields(settings.get_current());
+ settings_widget->exec();
+}
+
+void BigintWidget::reset() {
+ QSize size(scroll_area->viewport()->size());
+ qDebug() << "size" << size;
+ fw->cancel();
+ fw->waitForFinished();
+ settings.reset(128, size);
+ fw->setFuture(
+ QtConcurrent::mapped(settings.get_cells(), MandelSettings::iterate)
+ );
+ img_dirty = true;
+ update();
}
#include <QFutureWatcher>
#include <QLabel>
#include <QMenuBar>
+#include <QScrollArea>
#include <QStatusBar>
#include <QWidget>
#include "mandel.h"
+#include "settingswidget.h"
class BigintWidget : public QWidget {
Q_OBJECT
QFutureWatcher<MandelResultCell> *fw;
MandelSettings settings;
+ QScrollArea *scroll_area;
QLabel *img_label;
bool img_dirty;
QStatusBar *status_bar;
+ SettingsWidget *settings_widget;
public:
BigintWidget(QWidget *parent = nullptr);
~BigintWidget();
- QMenuBar *setup_menu_bar();
void finished_cell(int num);
void finished();
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void export_img();
+ void exec_settings_widget();
+ void reset();
};
#endif // BIGINTWIDGET_H
MandelResultCell::MandelResultCell(size_t iter, MpzPoint rpos)
: iter(iter), rpos(rpos) {}
+MandelParams::MandelParams() {}
+
MandelParams::MandelParams(
size_t max_iter,
QSize size,
}
}
-static inline MandelParams initial_params(size_t max_iter, const QSize size) {
- mpz_class one;
- MpzPoint center_f;
- int ione = std::min(size.width() / 3, size.height() / 3) / 2;
- ione--;
- ione |= ione >> 1;
- ione |= ione >> 2;
- ione |= ione >> 4;
- ione |= ione >> 8;
- ione |= ione >> 16;
- one = mpz_class(ione + 1);
- center_f = MpzPoint(one * -3 / 4, 0);
- return MandelParams(max_iter, size, center_f, one);
+static inline void setup_cells(
+ QVector<MandelCell> &cells, const MandelParams *current
+) {
+ QSize size = current->get_size();
+ QVector<MandelCell>::iterator i;
+ QPoint pos;
+
+ cells.resize(size.width() * size.height(), MandelCell(current));
+ for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++)
+ i->setup(pos);
}
MandelSettings::MandelSettings(size_t max_iter, const QSize size)
-: current(::initial_params(max_iter, size)), img(size, QImage::Format_RGB888)
+: img(nullptr)
{
- QVector<MandelCell>::iterator i;
- QPointF c(size.width() / 2., size.height() / 2.);
- QPoint pos;
-
- cells.resize(size.width() * size.height(), MandelCell(¤t));
- for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++) {
- i->set_pos(pos);
- }
+ reset(max_iter, size);
}
void MandelSettings::zoom(QPoint pos) {
QVector<MandelCell>::iterator i;
- MpzPoint p = cells[img.width() * pos.y() + pos.x()].get_rpos0();
+ MpzPoint p = cells[img->width() * pos.y() + pos.x()].get_rpos0();
current = MandelParams(
current.get_max_iter(),
current.get_size(),
- MpzPoint(p.get_x() * 8, p.get_y() * 8),
- current.get_one() * 8
+ MpzPoint(p.get_x() * 2, p.get_y() * 2),
+ current.get_one() * 2
);
- img.fill(Qt::GlobalColor::black);
- for (i = cells.begin(); i != cells.end(); i++)
- i->reset_iter_and_rpos();
+ img->fill(Qt::GlobalColor::black);
+ setup_cells(cells, ¤t);
}
void MandelSettings::finished_cell(int num, const MandelResultCell &result) {
size_t iter = result.get_iter();
cells[num].set_result(result);
- img.setPixelColor(
+ if (!img)
+ return;
+ img->setPixelColor(
cells[num].get_pos(),
iter < current.get_max_iter()
? colors[iter % colors.size()]
}
void MandelSettings::save_img(QString file_name) {
- img.save(file_name);
+ if (img)
+ img->save(file_name);
}
-void MandelCell::reset_rpos0() {
- QSize size(params->get_size());
- MpzPoint center_f = params->get_center_f();
- rpos0 = MpzPoint(
- center_f.get_x() + (pos.x() - size.width() / 2.),
- center_f.get_y() + (pos.y() - size.height() / 2.)
- );
+void MandelSettings::reset(size_t max_iter, const QSize size) {
+ mpz_class one;
+ MpzPoint center_f;
+ int ione = std::min(size.width(), size.height()) / 3;
+ ione--;
+ ione |= ione >> 1;
+ ione |= ione >> 2;
+ ione |= ione >> 4;
+ ione |= ione >> 8;
+ ione |= ione >> 16;
+ one = mpz_class(ione + 1);
+ center_f = MpzPoint(one * -3 / 4, 0);
+ current = MandelParams(max_iter, size, center_f, one);
+ delete img;
+ img = new QImage(size, QImage::Format_RGB888);
+ img->fill(Qt::GlobalColor::black);
+ setup_cells(cells, ¤t);
}
-MandelCell::MandelCell(MandelParams *params) : params(params) {}
+MandelCell::MandelCell(const MandelParams *params) : params(params) {}
MandelCell::MandelCell(const MandelCell &cell)
: params(cell.params), pos(cell.pos), result(cell.result),
rpos0(cell.rpos0) {}
-void MandelCell::set_result(const MandelResultCell &result) {
- this->result = result;
-}
-
-void MandelCell::reset_iter_and_rpos() {
- result = MandelResultCell();
- reset_rpos0();
-}
-
-void MandelCell::set_pos(QPoint pos) {
+void MandelCell::setup(const QPoint pos) {
+ QSize size(params->get_size());
+ MpzPoint center_f = params->get_center_f();
this->pos = pos;
- reset_rpos0();
+ rpos0 = MpzPoint(
+ center_f.get_x() + (pos.x() - size.width() / 2.),
+ center_f.get_y() + (pos.y() - size.height() / 2.)
+ );
+ result = MandelResultCell();
}
MandelResultCell MandelCell::iterate() const {
- MpzPoint rpos = this->result.rpos, sq;
+ MpzPoint rpos = result.rpos, sq;
mpz_class one = params->get_one(), four = one * one * 4;
mpz_class sqx, sqy;
- size_t iter = this->result.iter;
+ size_t iter = result.iter;
for (; iter < params->get_max_iter(); iter++) {
sqx = rpos.get_x() * rpos.get_x();
sqy = rpos.get_y() * rpos.get_y();
mpz_class one;
public:
+ MandelParams();
MandelParams(
size_t max_iter,
QSize size,
class MandelSettings {
MandelParams current;
- QImage img;
+ QImage *img;
QVector<MandelCell> cells;
public:
MandelSettings(size_t max_iter, QSize size);
- const QPixmap get_pixmap() const { return QPixmap::fromImage(img); }
- const QSize get_size() const { return current.get_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; }
void zoom(QPoint pos);
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);
};
class MandelCell {
- MandelParams *params;
+ const MandelParams *params;
QPoint pos;
MpzPoint rpos0;
MandelResultCell result;
-protected:
- void reset_rpos0();
-
public:
- MandelCell(MandelParams *params);
+ MandelCell(const MandelParams *params);
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; }
- void reset_iter_and_rpos();
- void set_result(const MandelResultCell &result);
- void set_pos(const QPoint pos);
+ void setup(const QPoint pos);
+ void set_result(const MandelResultCell &result) { this->result = result; }
MandelResultCell iterate() const;
};
--- /dev/null
+
+// settingswidget.cpp
+
+#include <QPushButton>
+#include <QLabel>
+#include <QLayout>
+
+#include "settingswidget.h"
+
+static QStringList labels = { "width", "height", "x", "y", "one" };
+
+SettingsWidget::SettingsWidget(QWidget *parent)
+: QDialog(parent),
+ width(new QLineEdit("", this)),
+ height(new QLineEdit("", this)),
+ x(new QLineEdit("", this)),
+ y(new QLineEdit("", this)),
+ one(new QLineEdit("", this))
+{
+ QPushButton *apply_button = new QPushButton("Apply");
+ QGridLayout *grid_layout = new QGridLayout(this);
+ QList<QLineEdit*> line_edits = { width, height, x, y, one };
+ int i;
+ setLayout(grid_layout);
+ for (i = 0; i < line_edits.size(); i++) {
+ grid_layout->addWidget(new QLabel(labels[i], this), i, 0);
+ line_edits[i]->setReadOnly(true);
+ line_edits[i]->setMinimumWidth(256);
+ grid_layout->addWidget(line_edits[i], i, 1);
+ }
+ connect(
+ apply_button,
+ &QPushButton::clicked,
+ this,
+ &QDialog::accept
+ );
+ grid_layout->addWidget(apply_button, i, 1);
+}
+
+void SettingsWidget::update_fields(const MandelParams params) {
+ QSize size = params.get_size();
+ MpzPoint center_f = params.get_center_f();
+ width->setText(QString::number(size.width()));
+ height->setText(QString::number(size.height()));
+ x->setText(QString::fromStdString(center_f.get_x().get_str()));
+ y->setText(QString::fromStdString(center_f.get_y().get_str()));
+ one->setText(QString::fromStdString(params.get_one().get_str()));
+}
--- /dev/null
+
+// settingswidget.h
+
+#ifndef SETTINGSWIDGET_H
+#define SETTINGSWIDGET_H
+
+#include <QDialog>
+#include <QLabel>
+#include <QLineEdit>
+
+#include "mandel.h"
+
+class SettingsWidget : public QDialog {
+ Q_OBJECT
+
+ QLineEdit *width, *height, *x, *y, *one;
+
+public:
+ SettingsWidget(QWidget *parent = nullptr);
+ void update_fields(const MandelParams params);
+};
+
+#endif // SETTINGSWIDGET_H