# Build directories
# -----------------
build-*/
+build/
// bigintwidget.cpp
+#include <QFileDialog>
#include <QLayout>
#include <QMouseEvent>
#include <QtConcurrent/QtConcurrent>
BigintWidget::BigintWidget(QWidget *parent)
: QWidget(parent),
fw(new QFutureWatcher<MandelResultCell>(this)),
- meta(8192, QSize(1800, 1000)),
+ meta(8192, QSize(1800, 900)),
img_label(new QLabel(this)),
- img_dirty(true)
+ img_dirty(true),
+ status_bar(new QStatusBar(this))
{
connect(
fw,
);
fw->setFuture(QtConcurrent::mapped(meta.get_cells(), MandelMeta::iterate));
setLayout(new QVBoxLayout());
+ layout()->addWidget(setup_menu_bar());
layout()->addWidget(img_label);
+ status_bar->setSizeGripEnabled(false);
+ layout()->addWidget(status_bar);
img_label->setMinimumSize(meta.get_size());
}
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);
+/*
+ menu = new QMenu("&Calcluation", this);
+ connect(
+ menu->addAction("&Double Max Iterations"),
+ &QAction::triggered,
+ this,
+ &meta.double_max_iter
+ );
+ connect(
+ menu->addAction("&Halve Max Iterations"),
+ &QAction::triggered,
+ this,
+ &meta.halve_max_iter
+ );
+*/
+ return menu_bar;
+}
+
void BigintWidget::finished_cell(int num) {
meta.finished_cell(num, fw->resultAt(num));
img_dirty = true;
update();
}
+static inline void calculating_status(
+ QStatusBar *status_bar, int &prev_num_threads
+) {
+ QTextStream ss(new QString());
+ int num_threads = QThreadPool::globalInstance()->activeThreadCount();
+ if (prev_num_threads == num_threads)
+ return;
+ ss << "Calculating with " << num_threads << " threads ...";
+ status_bar->showMessage(ss.readAll());
+ prev_num_threads = num_threads;
+}
+
+static inline void finished_status(QStatusBar *status_bar) {
+ status_bar->showMessage("Click the rendering to zoom.");
+}
+
void BigintWidget::paintEvent(QPaintEvent *event) {
+ static int prev_num_threads = -1;
if (img_dirty) {
img_label->setPixmap(meta.get_pixmap());
img_dirty = false;
+ if (fw->isFinished())
+ finished_status(status_bar);
+ else {
+ calculating_status(status_bar, prev_num_threads);
+ prev_num_threads = -1;
+ }
}
}
if (pos.x() < 0 || pos.x() >= meta.get_width()
|| pos.y() < 0 || pos.y() >= meta.get_height())
return;
- meta.zoom2x(pos);
+ meta.zoom(pos);
fw->setFuture(QtConcurrent::mapped(meta.get_cells(), MandelMeta::iterate));
img_dirty = true;
update();
}
+
+void BigintWidget::export_img() {
+ meta.save_img(
+ QFileDialog::getSaveFileName(
+ this, "Save image", "", "Images (*.png *.xpm *.jpg)"
+ )
+ );
+}
#include <QFutureWatcher>
#include <QLabel>
+#include <QMenuBar>
+#include <QStatusBar>
#include <QWidget>
#include "mandel.h"
MandelMeta meta;
QLabel *img_label;
bool img_dirty;
+ QStatusBar *status_bar;
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();
};
#endif // BIGINTWIDGET_H
// mandel.cpp
-#include <QDebug>
-
#include "colors.h"
#include "mandel.h"
MpzPoint::MpzPoint(mpz_class x, mpz_class y) : x(x), y(y) {}
MpzPoint::MpzPoint(const MpzPoint &other) : x(other.x), y(other.y) {}
-MandelResultCell::MandelResultCell() {}
+MandelResultCell::MandelResultCell() : iter(0) {}
MandelResultCell::MandelResultCell(size_t iter, MpzPoint rpos)
: iter(iter), rpos(rpos) {}
center_f = MpzPoint(one * -3 / 4, 0);
for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++) {
- i->set_meta(this);
i->set_pos(pos);
}
}
-void MandelMeta::zoom2x(QPoint pos) {
+void MandelMeta::zoom(QPoint pos) {
QVector<MandelCell>::iterator i;
MpzPoint p = cells[img.width() * pos.y() + pos.x()].get_rpos0();
center_f = MpzPoint(p.get_x() * 8, p.get_y() * 8);
i->reset_iter_and_rpos();
}
-void MandelMeta::finished_cell(int num, const MandelResultCell &cell) {
+void MandelMeta::finished_cell(int num, const MandelResultCell &result) {
+ size_t iter = result.get_iter();
+ cells[num].set_result(result);
img.setPixelColor(
- cells[num].update_result(cell.iter, cell.rpos),
- cell.iter < max_iter
- ? colors[cell.iter % colors.size()]
+ cells[num].get_pos(),
+ iter < max_iter
+ ? colors[iter % colors.size()]
: Qt::GlobalColor::black
);
}
return cell.iterate();
}
+void MandelMeta::save_img(QString file_name) {
+ img.save(file_name);
+}
+
void MandelCell::reset_rpos0() {
MpzPoint center_f = meta->get_center_f();
rpos0 = MpzPoint(
);
}
-MandelCell::MandelCell(MandelMeta *meta) : meta(meta), iter(0) {}
+MandelCell::MandelCell(MandelMeta *meta) : meta(meta) {}
MandelCell::MandelCell(const MandelCell &cell)
-: meta(cell.meta), pos(cell.pos), iter(cell.iter),
- rpos(cell.rpos), rpos0(cell.rpos0) {}
+: meta(cell.meta), pos(cell.pos), result(cell.result),
+ rpos0(cell.rpos0) {}
-QPoint MandelCell::update_result(size_t iter, const MpzPoint &rpos) {
- this->iter = iter;
- this->rpos = rpos;
- return pos;
+void MandelCell::set_result(const MandelResultCell &result) {
+ this->result = result;
}
void MandelCell::reset_iter_and_rpos() {
- iter = 0;
- rpos = MpzPoint();
+ result = MandelResultCell();
reset_rpos0();
}
-void MandelCell::set_meta(MandelMeta *meta) {
- this->meta = meta;
-}
-
void MandelCell::set_pos(QPoint pos) {
this->pos = pos;
reset_rpos0();
}
MandelResultCell MandelCell::iterate() const {
- MpzPoint rpos = this->rpos, sq;
+ MpzPoint rpos = this->result.rpos, sq;
mpz_class one = meta->get_one(), four = one * one * 4;
mpz_class sqx, sqy;
- size_t iter = this->iter;
+ size_t iter = this->result.iter;
for (; iter < meta->get_max_iter(); iter++) {
sqx = rpos.get_x() * rpos.get_x();
sqy = rpos.get_y() * rpos.get_y();
};
class MandelResultCell {
- friend class MandelMeta;
+ friend class MandelCell;
size_t iter;
MpzPoint rpos;
public:
MandelResultCell();
MandelResultCell(size_t iter, MpzPoint rpos);
+ const size_t get_iter() const { return iter; }
};
class MandelMeta {
+ /* max_iter, img size, center_f and one are parameters
+ * that we may want to adjust for our next calculation.
+ */
size_t max_iter;
QImage img;
QVector<MandelCell> cells;
const MpzPoint get_center_f() const { return center_f; }
const mpz_class get_one() const { return one; }
- void zoom2x(QPoint pos);
+ void zoom(QPoint pos);
void finished_cell(int num, const MandelResultCell &cell);
static MandelResultCell iterate(const MandelCell &cell);
+ void save_img(QString file_name);
};
class MandelCell {
MandelMeta *meta;
QPoint pos;
- size_t iter;
- MpzPoint rpos, rpos0;
+ MpzPoint rpos0;
+ MandelResultCell result;
protected:
void reset_rpos0();
public:
MandelCell(MandelMeta *meta);
MandelCell(const MandelCell &cell);
- inline const size_t get_iter() const { return iter; }
+ 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; }
- QPoint update_result(size_t iter, const MpzPoint &rpos);
void reset_iter_and_rpos();
- void set_meta(MandelMeta *meta);
+ void set_result(const MandelResultCell &result);
void set_pos(const QPoint pos);
MandelResultCell iterate() const;
};