]> git.mar77i.info Git - bigintmandel/commitdiff
extend user interface a bit
authormar77i <mar77i@protonmail.ch>
Mon, 1 Apr 2024 14:50:13 +0000 (16:50 +0200)
committermar77i <mar77i@protonmail.ch>
Mon, 1 Apr 2024 22:25:27 +0000 (00:25 +0200)
.gitignore
bigintwidget.cpp
bigintwidget.h
mandel.cpp
mandel.h

index 0c9e5c71912a1bc6edf6c3adc1df6a1a496031d6..95e83492e328c74a4419ceb94586bb6161f413b7 100644 (file)
@@ -75,3 +75,4 @@ CMakeLists.txt.user*
 # Build directories
 # -----------------
 build-*/
+build/
index 88a388943d8fb8edc1e64e621e895e7ea75fe3e2..5ae07cee3cea3543abafe4bef8146d4db863558c 100644 (file)
@@ -1,6 +1,7 @@
 
 // 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,
@@ -28,7 +30,10 @@ BigintWidget::BigintWidget(QWidget *parent)
     );
     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());
 }
 
@@ -37,6 +42,42 @@ 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);
+/*
+    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;
@@ -48,10 +89,33 @@ void BigintWidget::finished() {
     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;
+        }
     }
 }
 
@@ -62,8 +126,16 @@ void BigintWidget::mousePressEvent(QMouseEvent *event) {
     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)"
+        )
+    );
+}
index 5d1964b0fa71b35ebadf85eb63a0ecb9dffbaba4..6952bb240d9678327d335508f877ddbb85637ef8 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <QFutureWatcher>
 #include <QLabel>
+#include <QMenuBar>
+#include <QStatusBar>
 #include <QWidget>
 
 #include "mandel.h"
@@ -17,14 +19,17 @@ class BigintWidget : public QWidget {
     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
index 795b4e479b68728d354458c67c7735bb62a6af96..10e6b4d19af881e4127f8c955870ab43bde3ad95 100644 (file)
@@ -1,8 +1,6 @@
 
 // mandel.cpp
 
-#include <QDebug>
-
 #include "colors.h"
 #include "mandel.h"
 
@@ -10,7 +8,7 @@ MpzPoint::MpzPoint() : x(), y() {}
 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) {}
@@ -46,12 +44,11 @@ MandelMeta::MandelMeta(size_t max_iter, const QSize size)
 
     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);
@@ -61,11 +58,13 @@ void MandelMeta::zoom2x(QPoint pos) {
         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
     );
 }
@@ -74,6 +73,10 @@ MandelResultCell MandelMeta::iterate(const MandelCell &cell) {
     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(
@@ -82,38 +85,31 @@ void MandelCell::reset_rpos0() {
     );
 }
 
-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();
index 99ff14cccf767d7cdad74b56ce99b9ef8b7803bf..7876ec469bf9f0d41102e720c77e545ef96df25a 100644 (file)
--- a/mandel.h
+++ b/mandel.h
@@ -22,16 +22,20 @@ public:
 };
 
 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;
@@ -49,16 +53,17 @@ public:
     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();
@@ -66,12 +71,12 @@ protected:
 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;
 };