From f324e66569aace07e5c3dae138f3b81dfe5d2951 Mon Sep 17 00:00:00 2001 From: mar77i Date: Sat, 13 Apr 2024 00:52:44 +0200 Subject: [PATCH] add a basic settings dialog --- CMakeLists.txt | 2 + bigintwidget.cpp | 105 +++++++++++++++++++++++++++++++-------------- bigintwidget.h | 7 ++- mandel.cpp | 103 ++++++++++++++++++++++---------------------- mandel.h | 20 ++++----- settingswidget.cpp | 48 +++++++++++++++++++++ settingswidget.h | 23 ++++++++++ 7 files changed, 212 insertions(+), 96 deletions(-) create mode 100644 settingswidget.cpp create mode 100644 settingswidget.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f38274..7787013 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ set(PROJECT_SOURCES bigintwidget.h mandel.cpp mandel.h + settingswidget.cpp + settingswidget.h ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) diff --git a/bigintwidget.cpp b/bigintwidget.cpp index ed976c7..ed05441 100644 --- a/bigintwidget.cpp +++ b/bigintwidget.cpp @@ -4,20 +4,57 @@ #include #include #include -#include +#include #include #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(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, @@ -31,13 +68,15 @@ BigintWidget::BigintWidget(QWidget *parent) 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() { @@ -45,27 +84,6 @@ 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; @@ -97,6 +115,7 @@ void BigintWidget::paintEvent(QPaintEvent *event) { 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); @@ -110,21 +129,41 @@ void BigintWidget::paintEvent(QPaintEvent *event) { 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(); } diff --git a/bigintwidget.h b/bigintwidget.h index 6281bd9..1881852 100644 --- a/bigintwidget.h +++ b/bigintwidget.h @@ -7,29 +7,34 @@ #include #include #include +#include #include #include #include "mandel.h" +#include "settingswidget.h" class BigintWidget : public QWidget { Q_OBJECT QFutureWatcher *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 diff --git a/mandel.cpp b/mandel.cpp index 1140984..205a2a9 100644 --- a/mandel.cpp +++ b/mandel.cpp @@ -13,6 +13,8 @@ MandelResultCell::MandelResultCell() : iter(0) {} MandelResultCell::MandelResultCell(size_t iter, MpzPoint rpos) : iter(iter), rpos(rpos) {} +MandelParams::MandelParams() {} + MandelParams::MandelParams( size_t max_iter, QSize size, @@ -39,52 +41,43 @@ static inline void incrpos(QPoint &pos, const int width) { } } -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 &cells, const MandelParams *current +) { + QSize size = current->get_size(); + QVector::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::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::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()] @@ -97,43 +90,51 @@ MandelResultCell MandelSettings::iterate(const MandelCell &cell) { } 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(); diff --git a/mandel.h b/mandel.h index 5cd8b18..74377f7 100644 --- a/mandel.h +++ b/mandel.h @@ -40,6 +40,7 @@ private: mpz_class one; public: + MandelParams(); MandelParams( size_t max_iter, QSize size, @@ -56,40 +57,37 @@ public: class MandelSettings { MandelParams current; - QImage img; + QImage *img; QVector 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 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; }; diff --git a/settingswidget.cpp b/settingswidget.cpp new file mode 100644 index 0000000..fecc47f --- /dev/null +++ b/settingswidget.cpp @@ -0,0 +1,48 @@ + +// settingswidget.cpp + +#include +#include +#include + +#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 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())); +} diff --git a/settingswidget.h b/settingswidget.h new file mode 100644 index 0000000..cd5d178 --- /dev/null +++ b/settingswidget.h @@ -0,0 +1,23 @@ + +// settingswidget.h + +#ifndef SETTINGSWIDGET_H +#define SETTINGSWIDGET_H + +#include +#include +#include + +#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 -- 2.47.0