2 // bigintmandelwidget.cpp
9 #include <QtConcurrent/QtConcurrent>
12 #include "bigintmandelwidget.h"
14 static inline void start_calculation(
15 QFutureWatcher
<MandelResultCell
> *fw
, QVector
<MandelCell
> cells
20 [](const MandelCell
&cell
){ return cell
.iterate(); }
25 BigintMandelWidget::BigintMandelWidget(QWidget
*parent
)
27 fw(new QFutureWatcher
<MandelResultCell
>(this)),
28 settings(128, QSize(502, 334)),
29 menu_bar(new MenuBar(this)),
30 scroll_area(new QScrollArea(this)),
31 img_label(new QLabel(this)),
33 status_bar(new QStatusBar(this)),
34 settings_widget(new SettingsWidget(this)),
37 scroll_area
->setWidget(img_label
);
42 &BigintMandelWidget::settings_widget_accepted
46 &QFutureWatcher
<MandelResultCell
>::resultReadyAt
,
48 &BigintMandelWidget::finished_cell
52 &QFutureWatcher
<MandelResultCell
>::finished
,
54 &BigintMandelWidget::finished
56 start_calculation(fw
, settings
.get_cells());
57 setLayout(new QVBoxLayout());
58 layout()->addWidget(menu_bar
);
59 layout()->addWidget(scroll_area
);
60 status_bar
->setSizeGripEnabled(false);
61 layout()->addWidget(status_bar
);
62 img_label
->resize(settings
.get_params().get_size());
65 BigintMandelWidget::~BigintMandelWidget() {
67 fw
->waitForFinished();
70 void BigintMandelWidget::finished_cell(int num
) {
71 int y
= num
/ settings
.get_params().get_size().width();
72 if (y
> draw_progress
)
74 settings
.finished_cell(num
, fw
->resultAt(num
));
78 void BigintMandelWidget::finished() {
80 settings_widget
->set_finished(true);
84 static inline QPixmap
enhance_pixmap(QPixmap pixmap
, int draw_progress
) {
86 if (draw_progress
> -1) {
88 qp
.setPen(Qt::GlobalColor::gray
);
89 qp
.drawLine(0, draw_progress
, pixmap
.width() - 1, draw_progress
);
95 static inline void calculating_status(
96 QStatusBar
*status_bar
, int &prev_num_threads
98 QTextStream
ss(new QString());
99 int num_threads
= QThreadPool::globalInstance()->activeThreadCount();
100 if (prev_num_threads
== num_threads
)
102 ss
<< "Calculating with " << num_threads
<< " threads ...";
103 status_bar
->showMessage(ss
.readAll());
104 prev_num_threads
= num_threads
;
107 static inline void finished_status(QStatusBar
*status_bar
) {
108 status_bar
->showMessage("Click the rendering to zoom.");
111 void BigintMandelWidget::paintEvent(QPaintEvent
*event
) {
112 static int prev_num_threads
= -1;
115 img_label
->setPixmap(enhance_pixmap(settings
.get_pixmap(), draw_progress
));
116 img_label
->resize(img_label
->pixmap().size());
118 if (fw
->isFinished())
119 finished_status(status_bar
);
121 calculating_status(status_bar
, prev_num_threads
);
122 prev_num_threads
= -1;
126 void BigintMandelWidget::mousePressEvent(QMouseEvent
*event
) {
127 QSize
size(settings
.get_params().get_size());
128 QPoint
pos(event
->pos());
130 for (w
= img_label
; w
!= this; w
= w
->parentWidget())
131 pos
= w
->mapFromParent(pos
);
132 if (event
->button() != Qt::MouseButton::LeftButton
135 || pos
.x() >= size
.width()
137 || pos
.y() >= size
.height())
139 settings
.zoom(get_ideal_size(), menu_bar
->get_zoom_factor(), pos
);
140 start_calculation(fw
, settings
.get_cells());
144 void BigintMandelWidget::update_img() {
149 static inline QString
get_save_file_name(
150 QWidget
*parent
= nullptr,
151 const QString
&caption
= QString(),
152 const QString
&dir
= QString(),
153 const QString
&filter_title
= QString(),
154 const QStringList
&ext_list
= QStringList
{},
155 const QString default_ext
= QString()
157 QTextStream
ss(new QString());
158 QStringList::const_iterator ext_list_iter
;
161 ss
<< filter_title
<< " (" << ext_list
.join(" ") << ")";
162 file_name
= QFileDialog::getSaveFileName(
163 parent
, caption
, dir
, *ss
.string()
165 if (file_name
.isEmpty())
168 ss
.string()->clear();
170 pos
= file_name
.lastIndexOf(".");
171 if (pos
< 0 || !ext_list
.contains(file_name
.mid(pos
)))
176 void BigintMandelWidget::export_img() {
177 QString file_name
= get_save_file_name(
182 QStringList
{".png", ".xpm", ".jpg"},
185 if (!file_name
.isEmpty())
186 settings
.save_img(file_name
);
189 void BigintMandelWidget::exec_settings_widget() {
190 settings_widget
->update_fields(settings
.get_params(), fw
->isFinished());
191 settings_widget
->exec();
194 void BigintMandelWidget::reset() {
196 fw
->waitForFinished();
197 settings
.reset(128, get_ideal_size());
198 start_calculation(fw
, settings
.get_cells());
202 void BigintMandelWidget::settings_widget_accepted() {
203 settings
.set_max_iter(settings_widget
->get_max_iter().toULongLong());
204 start_calculation(fw
, settings
.get_cells());
208 void BigintMandelWidget::load_data() {
212 QString file_name
= QFileDialog::getOpenFileName(
213 this, "Load Data", "", "BigintMandel Data (*.json *.json.qcompress)"
215 if (file_name
.isEmpty())
217 file
.setFileName(file_name
);
218 if (!file
.open(QIODevice::ReadOnly
)) {
219 qWarning("Couldn't open save file.");
222 qba
= file
.readAll();
224 if (file_name
.endsWith(".qcompress"))
225 qba
= qUncompress(qba
);
226 settings
.from_json(QJsonDocument::fromJson(qba
).object());
230 void BigintMandelWidget::save_data() {
233 QString file_name
= get_save_file_name(
238 QStringList
{".json", ".json.qcompress"},
241 if (file_name
.isEmpty())
243 qba
= QJsonDocument(settings
.to_json()).toJson();
244 if (file_name
.endsWith(".qcompress"))
245 qba
= qCompress(qba
, 9);
246 file
.setFileName(file_name
);
247 if (!file
.open(QIODevice::WriteOnly
)) {
248 qWarning("Couldn't open save file.");