1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31
32 #include "ui/options_widget.h"
33
34 namespace colmap {
35
OptionsWidget(QWidget * parent)36 OptionsWidget::OptionsWidget(QWidget* parent) : QWidget(parent) {
37 setWindowFlags(Qt::Dialog);
38 setWindowModality(Qt::ApplicationModal);
39
40 QFont font;
41 font.setPointSize(10);
42 setFont(font);
43
44 grid_layout_ = new QGridLayout(this);
45 grid_layout_->setVerticalSpacing(3);
46 grid_layout_->setAlignment(Qt::AlignTop);
47 setLayout(grid_layout_);
48 }
49
AddOptionRow(const std::string & label_text,QWidget * widget,void * option)50 void OptionsWidget::AddOptionRow(const std::string& label_text, QWidget* widget,
51 void* option) {
52 QLabel* label = new QLabel(tr(label_text.c_str()), this);
53 label->setFont(font());
54 label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
55 grid_layout_->addWidget(label, grid_layout_->rowCount(), 0);
56
57 widget->setFont(font());
58 grid_layout_->addWidget(widget, grid_layout_->rowCount() - 1, 1);
59
60 option_rows_.emplace(option, std::make_pair(label, widget));
61 widget_rows_.emplace(widget, std::make_pair(label, widget));
62 }
63
AddWidgetRow(const std::string & label_text,QWidget * widget)64 void OptionsWidget::AddWidgetRow(const std::string& label_text,
65 QWidget* widget) {
66 QLabel* label = new QLabel(tr(label_text.c_str()), this);
67 label->setFont(font());
68 label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
69 grid_layout_->addWidget(label, grid_layout_->rowCount(), 0);
70
71 widget->setFont(font());
72 grid_layout_->addWidget(widget, grid_layout_->rowCount() - 1, 1);
73
74 widget_rows_.emplace(widget, std::make_pair(label, widget));
75 }
76
AddLayoutRow(const std::string & label_text,QLayout * layout)77 void OptionsWidget::AddLayoutRow(const std::string& label_text,
78 QLayout* layout) {
79 QLabel* label = new QLabel(tr(label_text.c_str()), this);
80 label->setFont(font());
81 label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
82 grid_layout_->addWidget(label, grid_layout_->rowCount(), 0);
83
84 QWidget* layout_widget = new QWidget(this);
85 layout_widget->setLayout(layout);
86 layout->setContentsMargins(0, 0, 0, 0);
87
88 grid_layout_->addWidget(layout_widget, grid_layout_->rowCount() - 1, 1);
89
90 layout_rows_.emplace(layout, std::make_pair(label, layout_widget));
91 }
92
AddOptionInt(int * option,const std::string & label_text,const int min,const int max)93 QSpinBox* OptionsWidget::AddOptionInt(int* option,
94 const std::string& label_text,
95 const int min, const int max) {
96 QSpinBox* spinbox = new QSpinBox(this);
97 spinbox->setMinimum(min);
98 spinbox->setMaximum(max);
99
100 AddOptionRow(label_text, spinbox, option);
101
102 options_int_.emplace_back(spinbox, option);
103
104 return spinbox;
105 }
106
AddOptionDouble(double * option,const std::string & label_text,const double min,const double max,const double step,const int decimals)107 QDoubleSpinBox* OptionsWidget::AddOptionDouble(
108 double* option, const std::string& label_text, const double min,
109 const double max, const double step, const int decimals) {
110 QDoubleSpinBox* spinbox = new QDoubleSpinBox(this);
111 spinbox->setMinimum(min);
112 spinbox->setMaximum(max);
113 spinbox->setSingleStep(step);
114 spinbox->setDecimals(decimals);
115
116 AddOptionRow(label_text, spinbox, option);
117
118 options_double_.emplace_back(spinbox, option);
119
120 return spinbox;
121 }
122
AddOptionDoubleLog(double * option,const std::string & label_text,const double min,const double max,const double step,const int decimals)123 QDoubleSpinBox* OptionsWidget::AddOptionDoubleLog(
124 double* option, const std::string& label_text, const double min,
125 const double max, const double step, const int decimals) {
126 QDoubleSpinBox* spinbox = new QDoubleSpinBox(this);
127 spinbox->setMinimum(min);
128 spinbox->setMaximum(max);
129 spinbox->setSingleStep(step);
130 spinbox->setDecimals(decimals);
131
132 AddOptionRow(label_text, spinbox, option);
133
134 options_double_log_.emplace_back(spinbox, option);
135
136 return spinbox;
137 }
138
AddOptionBool(bool * option,const std::string & label_text)139 QCheckBox* OptionsWidget::AddOptionBool(bool* option,
140 const std::string& label_text) {
141 QCheckBox* checkbox = new QCheckBox(this);
142
143 AddOptionRow(label_text, checkbox, option);
144
145 options_bool_.emplace_back(checkbox, option);
146
147 return checkbox;
148 }
149
AddOptionText(std::string * option,const std::string & label_text)150 QLineEdit* OptionsWidget::AddOptionText(std::string* option,
151 const std::string& label_text) {
152 QLineEdit* line_edit = new QLineEdit(this);
153
154 AddOptionRow(label_text, line_edit, option);
155
156 options_text_.emplace_back(line_edit, option);
157
158 return line_edit;
159 }
160
AddOptionFilePath(std::string * option,const std::string & label_text)161 QLineEdit* OptionsWidget::AddOptionFilePath(std::string* option,
162 const std::string& label_text) {
163 QLineEdit* line_edit = new QLineEdit(this);
164
165 AddOptionRow(label_text, line_edit, option);
166
167 auto SelectPathFunc = [this, line_edit]() {
168 line_edit->setText(QFileDialog::getOpenFileName(this, tr("Select file")));
169 };
170
171 QPushButton* select_button = new QPushButton(tr("Select file"), this);
172 select_button->setFont(font());
173 connect(select_button, &QPushButton::released, this, SelectPathFunc);
174 grid_layout_->addWidget(select_button, grid_layout_->rowCount(), 1);
175
176 options_path_.emplace_back(line_edit, option);
177
178 return line_edit;
179 }
180
AddOptionDirPath(std::string * option,const std::string & label_text)181 QLineEdit* OptionsWidget::AddOptionDirPath(std::string* option,
182 const std::string& label_text) {
183 QLineEdit* line_edit = new QLineEdit(this);
184
185 AddOptionRow(label_text, line_edit, option);
186
187 auto SelectPathFunc = [this, line_edit]() {
188 line_edit->setText(
189 QFileDialog::getExistingDirectory(this, tr("Select folder")));
190 };
191
192 QPushButton* select_button = new QPushButton(tr("Select folder"), this);
193 select_button->setFont(font());
194 connect(select_button, &QPushButton::released, this, SelectPathFunc);
195 grid_layout_->addWidget(select_button, grid_layout_->rowCount(), 1);
196
197 options_path_.emplace_back(line_edit, option);
198
199 return line_edit;
200 }
201
AddSpacer()202 void OptionsWidget::AddSpacer() {
203 QLabel* label = new QLabel("", this);
204 label->setFont(font());
205 grid_layout_->addWidget(label, grid_layout_->rowCount(), 0, 2, 1);
206 }
207
AddSection(const std::string & title)208 void OptionsWidget::AddSection(const std::string& title) {
209 QLabel* label = new QLabel(tr(title.c_str()), this);
210 label->setFont(font());
211 label->setContentsMargins(0, 0, 0, 5);
212 grid_layout_->addWidget(label, grid_layout_->rowCount(), 0, 1, 2,
213 Qt::AlignHCenter);
214 }
215
ReadOptions()216 void OptionsWidget::ReadOptions() {
217 for (auto& option : options_int_) {
218 option.first->setValue(*option.second);
219 }
220
221 for (auto& option : options_double_) {
222 option.first->setValue(*option.second);
223 }
224
225 for (auto& option : options_double_log_) {
226 option.first->setValue(std::log10(*option.second));
227 }
228
229 for (auto& option : options_bool_) {
230 option.first->setChecked(*option.second);
231 }
232
233 for (auto& option : options_text_) {
234 option.first->setText(QString::fromStdString(*option.second));
235 }
236
237 for (auto& option : options_path_) {
238 option.first->setText(QString::fromStdString(*option.second));
239 }
240 }
241
WriteOptions()242 void OptionsWidget::WriteOptions() {
243 for (auto& option : options_int_) {
244 *option.second = option.first->value();
245 }
246
247 for (auto& option : options_double_) {
248 *option.second = option.first->value();
249 }
250
251 for (auto& option : options_double_log_) {
252 *option.second = std::pow(10, option.first->value());
253 }
254
255 for (auto& option : options_bool_) {
256 *option.second = option.first->isChecked();
257 }
258
259 for (auto& option : options_text_) {
260 *option.second = option.first->text().toUtf8().constData();
261 }
262
263 for (auto& option : options_path_) {
264 *option.second = option.first->text().toUtf8().constData();
265 }
266 }
267
showEvent(QShowEvent * event)268 void OptionsWidget::showEvent(QShowEvent* event) { ReadOptions(); }
269
closeEvent(QCloseEvent * event)270 void OptionsWidget::closeEvent(QCloseEvent* event) { WriteOptions(); }
271
hideEvent(QHideEvent * event)272 void OptionsWidget::hideEvent(QHideEvent* event) { WriteOptions(); }
273
ShowOption(void * option)274 void OptionsWidget::ShowOption(void* option) {
275 auto& option_row = option_rows_.at(option);
276 option_row.first->show();
277 option_row.second->show();
278 }
279
HideOption(void * option)280 void OptionsWidget::HideOption(void* option) {
281 auto& option_row = option_rows_.at(option);
282 option_row.first->hide();
283 option_row.second->hide();
284 }
285
ShowWidget(QWidget * widget)286 void OptionsWidget::ShowWidget(QWidget* widget) {
287 auto& widget_row = widget_rows_.at(widget);
288 widget_row.first->show();
289 widget_row.second->show();
290 }
291
HideWidget(QWidget * widget)292 void OptionsWidget::HideWidget(QWidget* widget) {
293 auto& widget_row = widget_rows_.at(widget);
294 widget_row.first->hide();
295 widget_row.second->hide();
296 }
297
ShowLayout(QLayout * layout)298 void OptionsWidget::ShowLayout(QLayout* layout) {
299 auto& layout_row = layout_rows_.at(layout);
300 layout_row.first->show();
301 layout_row.second->show();
302 }
303
HideLayout(QLayout * layout)304 void OptionsWidget::HideLayout(QLayout* layout) {
305 auto& layout_row = layout_rows_.at(layout);
306 layout_row.first->hide();
307 layout_row.second->hide();
308 }
309
310 } // namespace colmap
311