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