]> git.mar77i.info Git - bigintmandel/commitdiff
add a basic settings dialog
authormar77i <mar77i@protonmail.ch>
Fri, 12 Apr 2024 22:52:44 +0000 (00:52 +0200)
committermar77i <mar77i@protonmail.ch>
Fri, 12 Apr 2024 22:52:44 +0000 (00:52 +0200)
CMakeLists.txt
bigintwidget.cpp
bigintwidget.h
mandel.cpp
mandel.h
settingswidget.cpp [new file with mode: 0644]
settingswidget.h [new file with mode: 0644]

index 8f38274f0cddb22124cd9db2070d9d7e5e90aaca..7787013f34edc2c93c80036e4d2ead94d24c09fc 100644 (file)
@@ -18,6 +18,8 @@ set(PROJECT_SOURCES
         bigintwidget.h
         mandel.cpp
         mandel.h
+        settingswidget.cpp
+        settingswidget.h
 )
 
 if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
index ed976c73f056d63e3e71f0d0a15d77f7c3fb3498..ed054412584aa0cab9f24c8c395cf77ac76d48b1 100644 (file)
@@ -4,20 +4,57 @@
 #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,
@@ -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();
 }
index 6281bd9b7644b91ea4f8c61e3041985311978876..188185243c40d6c3a98afd2256052d010c8d0cba 100644 (file)
@@ -7,29 +7,34 @@
 #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
index 1140984fbc00addb2c99e1778cb75dbfb4bfac30..205a2a99144a718332cedffc32e08a6e55d9c7f7 100644 (file)
@@ -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<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(&current));
-    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, &current);
 }
 
 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, &current);
 }
 
-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();
index 5cd8b18d22bb6446a9fa405f385c49a9c4dac049..74377f755934fc4f1487e5e379aa30af908ebcdb 100644 (file)
--- 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<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;
 };
 
diff --git a/settingswidget.cpp b/settingswidget.cpp
new file mode 100644 (file)
index 0000000..fecc47f
--- /dev/null
@@ -0,0 +1,48 @@
+
+// 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()));
+}
diff --git a/settingswidget.h b/settingswidget.h
new file mode 100644 (file)
index 0000000..cd5d178
--- /dev/null
@@ -0,0 +1,23 @@
+
+// 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