]> git.mar77i.info Git - bigintmandel/blob - bigintmandelwidget.cpp
make zoom_factor part of MandelSettings
[bigintmandel] / bigintmandelwidget.cpp
1
2 /*
3 * bigintmandelwidget.cpp
4 *
5 * This file is covered by the LICENSE file in the root of this project.
6 */
7
8 #include <QFileDialog>
9 #include <QLayout>
10 #include <QMouseEvent>
11 #include <QPainter>
12 #include <QPushButton>
13 #include <QtConcurrent/QtConcurrent>
14
15 #include "bigintmandelwidget.h"
16 #include "mandellabel.h"
17 #include "menubar.h"
18 #include "settingswidget.h"
19
20 BigintMandelWidget::BigintMandelWidget(QWidget *parent)
21 : QWidget(parent),
22 fw(new QFutureWatcher<MandelResultCell>(this)),
23 settings(128, QSize(502, 334)),
24 menu_bar(new MenuBar(this)),
25 scroll_area(new QScrollArea(this)),
26 mandel_label(new MandelLabel(this)),
27 status_bar(new QStatusBar(this)),
28 settings_widget(new SettingsWidget(this))
29 {
30 scroll_area->setWidget(mandel_label);
31 connect(
32 settings_widget,
33 &QDialog::accepted,
34 this,
35 &BigintMandelWidget::settings_widget_accepted
36 );
37 connect(
38 fw,
39 &QFutureWatcher<MandelResultCell>::resultReadyAt,
40 this,
41 &BigintMandelWidget::finished_cell
42 );
43 connect(
44 fw,
45 &QFutureWatcher<MandelResultCell>::finished,
46 this,
47 &BigintMandelWidget::finished
48 );
49 setLayout(new QVBoxLayout());
50 layout()->addWidget(menu_bar);
51 layout()->addWidget(scroll_area);
52 status_bar->setSizeGripEnabled(false);
53 layout()->addWidget(status_bar);
54 mandel_label->resize(settings.get_params().get_size());
55 start();
56 }
57
58 BigintMandelWidget::~BigintMandelWidget() {
59 stop();
60 }
61
62 void BigintMandelWidget::finished_cell(int num) {
63 QSize size = settings.get_params().get_size();
64 int y = num / size.width() + 1;
65 mandel_label->set_draw_progress(y < size.height() - 1 ? y + 1 : -1);
66 settings.finished_cell(num, fw->resultAt(num));
67 update();
68 }
69
70 void BigintMandelWidget::finished() {
71 mandel_label->set_draw_progress(-1);
72 update();
73 }
74
75 void BigintMandelWidget::update_status_bar() {
76 QTextStream ss;
77 static int prev_num_threads = -1;
78 int num_threads;
79 if (fw->isFinished())
80 num_threads = -1;
81 else
82 num_threads = QThreadPool::globalInstance()->activeThreadCount();
83 if (num_threads == prev_num_threads)
84 return;
85 ss.setString(new QString());
86 if (num_threads != -1)
87 ss << "Calculating with " << num_threads << " threads ...";
88 else if (settings.get_zoom_factor() == -1)
89 ss << "Choose a zoom factor from the \"Zoom\" menu.";
90 else
91 ss << "Click the rendering to zoom.";
92 status_bar->showMessage(*ss.string());
93 prev_num_threads = num_threads;
94 }
95
96 void BigintMandelWidget::start() {
97 stop();
98 fw->setFuture(
99 QtConcurrent::mapped(
100 settings.get_cells(),
101 [](const MandelCell &cell){ return cell.iterate(); }
102 )
103 );
104 settings.set_zoom_factor(-1);
105 update();
106 }
107
108 void BigintMandelWidget::stop() {
109 fw->cancel();
110 fw->waitForFinished();
111 }
112
113 void BigintMandelWidget::mousePressEvent(QMouseEvent *event) {
114 QSize size(settings.get_params().get_size());
115 QPoint pos(event->pos());
116 QWidget *w;
117 int zoom_factor = settings.get_zoom_factor();
118 for (w = mandel_label; w != this; w = w->parentWidget())
119 pos = w->mapFromParent(pos);
120 if (event->button() != Qt::MouseButton::LeftButton
121 || !fw->isFinished()
122 || pos.x() < 0
123 || pos.x() >= size.width()
124 || pos.y() < 0
125 || pos.y() >= size.height()
126 || zoom_factor == -1)
127 return;
128 settings.zoom(get_ideal_size(), zoom_factor, pos);
129 start();
130 }
131
132 static inline QString get_save_file_name(
133 QWidget *parent = nullptr,
134 const QString &caption = QString(),
135 const QString &dir = QString(),
136 const QString &filter_title = QString(),
137 const QStringList &ext_list = QStringList{},
138 const QString default_ext = QString()
139 ) {
140 QTextStream ss(new QString());
141 QStringList::const_iterator ext_list_iter;
142 QString file_name;
143 ss << filter_title << " (" << ext_list.join(" ") << ")";
144 file_name = QFileDialog::getSaveFileName(
145 parent, caption, dir, *ss.string()
146 );
147 if (file_name.isEmpty())
148 return file_name;
149 ss.string()->clear();
150 ss << file_name;
151 for (
152 ext_list_iter = ext_list.constBegin();
153 ext_list_iter != ext_list.constEnd();
154 ext_list_iter++
155 )
156 if (file_name.endsWith(*ext_list_iter))
157 break;
158 if (ext_list_iter == ext_list.constEnd())
159 ss << default_ext;
160 return *ss.string();
161 }
162
163 void BigintMandelWidget::export_img() {
164 QString file_name = get_save_file_name(
165 this,
166 "Save image",
167 "",
168 "Images",
169 QStringList{".png", ".xpm", ".jpg"},
170 ".png"
171 );
172 if (!file_name.isEmpty())
173 settings.save_img(file_name);
174 }
175
176 void BigintMandelWidget::exec_settings_widget() {
177 settings_widget->update_params(settings.get_params());
178 settings_widget->exec();
179 }
180
181 void BigintMandelWidget::reset() {
182 settings.reset(128, get_ideal_size());
183 start();
184 }
185
186 void BigintMandelWidget::settings_widget_accepted() {
187 if (settings_widget->is_clear_image_checked()) {
188 settings.set_params(settings_widget->get_params());
189 settings.clear();
190 } else {
191 quint64 max_iter = settings_widget->get_max_iter();
192 if (max_iter <= settings.get_max_iter())
193 return;
194 settings.set_max_iter(max_iter);
195 }
196 start();
197 }
198
199 void BigintMandelWidget::load_data() {
200 QFile file;
201 QJsonObject json;
202 QByteArray qba;
203 QString file_name = QFileDialog::getOpenFileName(
204 this, "Load Data", "", "BigintMandel Data (*.json *.json.qcompress)"
205 );
206 if (file_name.isEmpty())
207 return;
208 file.setFileName(file_name);
209 if (!file.open(QIODevice::ReadOnly)) {
210 qWarning("Couldn't open save file.");
211 return;
212 }
213 qba = file.readAll();
214 file.close();
215 if (file_name.endsWith(".qcompress"))
216 qba = qUncompress(qba);
217 settings.from_json(QJsonDocument::fromJson(qba).object());
218 update();
219 }
220
221 void BigintMandelWidget::save_data() {
222 QFile file;
223 QByteArray qba;
224 QString file_name = get_save_file_name(
225 this,
226 "Save data",
227 "",
228 "Bigintmandel Data",
229 QStringList{".json", ".json.qcompress"},
230 ".json.qcompress"
231 );
232 if (file_name.isEmpty())
233 return;
234 qba = QJsonDocument(settings.to_json()).toJson();
235 if (file_name.endsWith(".qcompress"))
236 qba = qCompress(qba, 9);
237 file.setFileName(file_name);
238 if (!file.open(QIODevice::WriteOnly)) {
239 qWarning("Couldn't open save file.");
240 return;
241 }
242 file.write(qba);
243 file.close();
244 }
245
246 void BigintMandelWidget::update() {
247 update_status_bar();
248 QWidget::update();
249 }
250
251 void BigintMandelWidget::resize_to_window() {
252 QSize size = get_ideal_size();
253 if (size == settings.get_params().get_size())
254 return;
255 settings.set_size(size);
256 settings.clear();
257 start();
258 }