1 /* -*- C++ -*-
2 * This file is part of RawTherapee.
3 *
4 * Copyright (c) 2017 Alberto Griggio
5 *
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "dynamicprofilepanel.h"
21 #include "multilangmgr.h"
22 #include "../rtengine/profilestore.h"
23 #include "../rtengine/rtengine.h"
24 #include "../rtengine/dynamicprofile.h"
25 #include <sstream>
26 #include <iomanip>
27
28
29 //-----------------------------------------------------------------------------
30 // DynamicProfilePanel::EditDialog
31 //-----------------------------------------------------------------------------
32
EditDialog(const Glib::ustring & title,Gtk::Window & parent)33 DynamicProfilePanel::EditDialog::EditDialog (const Glib::ustring &title, Gtk::Window &parent):
34 Gtk::Dialog (title, parent)
35 {
36 profilepath_ = Gtk::manage (new ProfileStoreComboBox());
37 Gtk::HBox *hb = Gtk::manage (new Gtk::HBox());
38 hb->pack_start (*Gtk::manage (new Gtk::Label (M ("DYNPROFILEEDITOR_PROFILE"))), false, false, 4);
39 hb->pack_start (*profilepath_, true, true, 2);
40 get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4);
41
42 add_optional (M ("EXIFFILTER_CAMERA"), has_camera_, camera_);
43 add_optional (M ("EXIFFILTER_LENS"), has_lens_, lens_);
44
45 imagetype_ = Gtk::manage (new MyComboBoxText());
46 imagetype_->append(Glib::ustring("(") + M("DYNPROFILEEDITOR_IMGTYPE_ANY") + ")");
47 imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_STD"));
48 imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_HDR"));
49 imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_PS"));
50 imagetype_->set_active(0);
51 hb = Gtk::manage (new Gtk::HBox());
52 hb->pack_start (*Gtk::manage (new Gtk::Label (M ("EXIFFILTER_IMAGETYPE"))), false, false, 4);
53 hb->pack_start (*imagetype_, true, true, 2);
54 get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4);
55
56 add_range (M ("EXIFFILTER_ISO"), iso_min_, iso_max_);
57 add_range (M ("EXIFFILTER_APERTURE"), fnumber_min_, fnumber_max_);
58 add_range (M ("EXIFFILTER_FOCALLEN"), focallen_min_, focallen_max_);
59 add_range (M ("EXIFFILTER_SHUTTER"), shutterspeed_min_, shutterspeed_max_);
60 add_range (M ("EXIFFILTER_EXPOSURECOMPENSATION"), expcomp_min_, expcomp_max_);
61
62 add_button (M ("GENERAL_OK"), 1);
63 add_button (M ("GENERAL_CANCEL"), 2);
64
65 set_ranges();
66
67 show_all_children();
68 }
69
70
set_rule(const DynamicProfileRule & rule)71 void DynamicProfilePanel::EditDialog::set_rule (
72 const DynamicProfileRule &rule)
73 {
74 iso_min_->set_value (rule.iso.min);
75 iso_max_->set_value (rule.iso.max);
76
77 fnumber_min_->set_value (rule.fnumber.min);
78 fnumber_max_->set_value (rule.fnumber.max);
79
80 focallen_min_->set_value (rule.focallen.min);
81 focallen_max_->set_value (rule.focallen.max);
82
83 shutterspeed_min_->set_value (rule.shutterspeed.min);
84 shutterspeed_max_->set_value (rule.shutterspeed.max);
85
86 expcomp_min_->set_value (rule.expcomp.min);
87 expcomp_max_->set_value (rule.expcomp.max);
88
89 has_camera_->set_active (rule.camera.enabled);
90 camera_->set_text (rule.camera.value);
91
92 has_lens_->set_active (rule.lens.enabled);
93 lens_->set_text (rule.lens.value);
94
95 if (!rule.imagetype.enabled) {
96 imagetype_->set_active(0);
97 } else if (rule.imagetype.value == "STD") {
98 imagetype_->set_active(1);
99 } else if (rule.imagetype.value == "HDR") {
100 imagetype_->set_active(2);
101 } else if (rule.imagetype.value == "PS") {
102 imagetype_->set_active(3);
103 } else {
104 imagetype_->set_active(0);
105 }
106
107 profilepath_->updateProfileList();
108
109 if (!profilepath_->setActiveRowFromFullPath (rule.profilepath)) {
110 profilepath_->setInternalEntry();
111 }
112 }
113
get_rule()114 DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule()
115 {
116 DynamicProfileRule ret;
117 ret.iso.min = iso_min_->get_value_as_int();
118 ret.iso.max = iso_max_->get_value_as_int();
119
120 ret.fnumber.min = fnumber_min_->get_value();
121 ret.fnumber.max = fnumber_max_->get_value();
122
123 ret.focallen.min = focallen_min_->get_value();
124 ret.focallen.max = focallen_max_->get_value();
125
126 ret.shutterspeed.min = shutterspeed_min_->get_value();
127 ret.shutterspeed.max = shutterspeed_max_->get_value();
128
129 ret.expcomp.min = expcomp_min_->get_value();
130 ret.expcomp.max = expcomp_max_->get_value();
131
132 ret.camera.enabled = has_camera_->get_active();
133 ret.camera.value = camera_->get_text();
134
135 ret.lens.enabled = has_lens_->get_active();
136 ret.lens.value = lens_->get_text();
137
138 ret.imagetype.enabled = imagetype_->get_active_row_number() > 0;
139 switch (imagetype_->get_active_row_number()) {
140 case 1:
141 ret.imagetype.value = "STD";
142 break;
143 case 2:
144 ret.imagetype.value = "HDR";
145 break;
146 case 3:
147 ret.imagetype.value = "PS";
148 break;
149 default:
150 ret.imagetype.value = "";
151 }
152
153 ret.profilepath = profilepath_->getFullPathFromActiveRow();
154
155 return ret;
156 }
157
set_ranges()158 void DynamicProfilePanel::EditDialog::set_ranges()
159 {
160 DynamicProfileRule default_rule;
161 iso_min_->set_digits (0);
162 iso_max_->set_digits (0);
163 iso_min_->set_increments (1, 10);
164 iso_max_->set_increments (1, 10);
165 iso_min_->set_range (default_rule.iso.min, default_rule.iso.max);
166 iso_max_->set_range (default_rule.iso.min, default_rule.iso.max);
167 iso_min_->set_value (default_rule.iso.min);
168 iso_max_->set_value (default_rule.iso.max);
169
170 #define DOIT_(name) \
171 name ## _min_->set_digits(1); \
172 name ## _max_->set_digits(1); \
173 name ## _min_->set_increments(0.1, 1); \
174 name ## _max_->set_increments(0.1, 1); \
175 name ## _min_->set_range(default_rule. name .min, \
176 default_rule. name .max); \
177 name ## _max_->set_range(default_rule. name .min, \
178 default_rule. name .max); \
179 name ## _min_->set_value(default_rule. name .min); \
180 name ## _max_->set_value(default_rule. name .max)
181
182 DOIT_ (fnumber);
183 DOIT_ (focallen);
184 DOIT_ (shutterspeed);
185 DOIT_ (expcomp);
186 #undef DOIT_
187 shutterspeed_min_->set_digits (4);
188 shutterspeed_max_->set_digits (4);
189
190 profilepath_->setInternalEntry();
191 }
192
193
add_range(const Glib::ustring & name,Gtk::SpinButton * & from,Gtk::SpinButton * & to)194 void DynamicProfilePanel::EditDialog::add_range (const Glib::ustring &name,
195 Gtk::SpinButton *&from, Gtk::SpinButton *&to)
196 {
197 Gtk::HBox *hb = Gtk::manage (new Gtk::HBox());
198 hb->pack_start (*Gtk::manage (new Gtk::Label (name)), false, false, 4);
199 from = Gtk::manage (new Gtk::SpinButton());
200 to = Gtk::manage (new Gtk::SpinButton());
201 from->set_numeric (true);
202 to->set_numeric (true);
203 hb->pack_start (*from, true, true, 2);
204 hb->pack_start (*Gtk::manage (new Gtk::Label (" - ")), false, false, 4);
205 hb->pack_start (*to, true, true, 2);
206 get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4);
207 }
208
add_optional(const Glib::ustring & name,Gtk::CheckButton * & check,Gtk::Entry * & field)209 void DynamicProfilePanel::EditDialog::add_optional (const Glib::ustring &name, Gtk::CheckButton *&check, Gtk::Entry *&field)
210 {
211 check = Gtk::manage (new Gtk::CheckButton (name));
212 Gtk::HBox *hb = Gtk::manage (new Gtk::HBox());
213 hb->pack_start (*check, Gtk::PACK_SHRINK, 4);
214 field = Gtk::manage (new Gtk::Entry());
215 hb->pack_start (*field, true, true, 2);
216 get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4);
217 field->set_tooltip_text (M ("DYNPROFILEEDITOR_ENTRY_TOOLTIP"));
218 }
219
220
221 //-----------------------------------------------------------------------------
222 // DynamicProfilePanel
223 //-----------------------------------------------------------------------------
224
DynamicProfilePanel()225 DynamicProfilePanel::DynamicProfilePanel():
226 vbox_ (Gtk::ORIENTATION_VERTICAL),
227 button_up_ (M ("DYNPROFILEEDITOR_MOVE_UP")),
228 button_down_ (M ("DYNPROFILEEDITOR_MOVE_DOWN")),
229 button_new_ (M ("DYNPROFILEEDITOR_NEW")),
230 button_edit_ (M ("DYNPROFILEEDITOR_EDIT")),
231 button_delete_ (M ("DYNPROFILEEDITOR_DELETE"))
232 {
233 add (vbox_);
234
235 treeview_.set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_VERTICAL);
236 scrolledwindow_.add (treeview_);
237
238 scrolledwindow_.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
239
240 vbox_.pack_start (scrolledwindow_);
241 vbox_.pack_start (buttonbox_, Gtk::PACK_SHRINK);
242
243 buttonbox_.pack_start (button_new_, Gtk::PACK_SHRINK);
244 buttonbox_.pack_start (button_edit_, Gtk::PACK_SHRINK);
245 buttonbox_.pack_start (button_delete_, Gtk::PACK_SHRINK);
246 buttonbox_.pack_start (button_up_, Gtk::PACK_SHRINK);
247 buttonbox_.pack_start (button_down_, Gtk::PACK_SHRINK);
248 buttonbox_.set_border_width (5);
249 buttonbox_.set_layout (Gtk::BUTTONBOX_END);
250 button_up_.signal_clicked().connect (
251 sigc::mem_fun (*this, &DynamicProfilePanel::on_button_up));
252 button_down_.signal_clicked().connect (
253 sigc::mem_fun (*this, &DynamicProfilePanel::on_button_down));
254 button_new_.signal_clicked().connect (
255 sigc::mem_fun (*this, &DynamicProfilePanel::on_button_new));
256 button_edit_.signal_clicked().connect (
257 sigc::mem_fun (*this, &DynamicProfilePanel::on_button_edit));
258 button_delete_.signal_clicked().connect (
259 sigc::mem_fun (*this, &DynamicProfilePanel::on_button_delete));
260
261 treemodel_ = Gtk::ListStore::create (columns_);
262 treeview_.set_model (treemodel_);
263
264 auto cell = Gtk::manage (new Gtk::CellRendererText());
265 int cols_count = treeview_.append_column ( M ("DYNPROFILEEDITOR_PROFILE"), *cell);
266 auto col = treeview_.get_column (cols_count - 1);
267
268 if (col) {
269 col->set_cell_data_func (
270 *cell, sigc::mem_fun (
271 *this, &DynamicProfilePanel::render_profilepath));
272 }
273
274 cell = Gtk::manage (new Gtk::CellRendererText());
275 cols_count = treeview_.append_column (
276 M ("EXIFFILTER_CAMERA"), *cell);
277 col = treeview_.get_column (cols_count - 1);
278
279 if (col) {
280 col->set_cell_data_func (
281 *cell, sigc::mem_fun (
282 *this, &DynamicProfilePanel::render_camera));
283 }
284
285 cell = Gtk::manage (new Gtk::CellRendererText());
286 cols_count = treeview_.append_column (M ("EXIFFILTER_LENS"), *cell);
287 col = treeview_.get_column (cols_count - 1);
288
289 if (col) {
290 col->set_cell_data_func (
291 *cell, sigc::mem_fun (
292 *this, &DynamicProfilePanel::render_lens));
293 }
294
295 cell = Gtk::manage (new Gtk::CellRendererText());
296 cols_count = treeview_.append_column (M ("EXIFFILTER_IMAGETYPE"), *cell);
297 col = treeview_.get_column (cols_count - 1);
298
299 if (col) {
300 col->set_cell_data_func (
301 *cell, sigc::mem_fun (
302 *this, &DynamicProfilePanel::render_imagetype));
303 }
304
305 cell = Gtk::manage (new Gtk::CellRendererText());
306 cols_count = treeview_.append_column (M ("EXIFFILTER_ISO"), *cell);
307 col = treeview_.get_column (cols_count - 1);
308
309 if (col) {
310 col->set_cell_data_func (
311 *cell, sigc::mem_fun (
312 *this, &DynamicProfilePanel::render_iso));
313 }
314
315 cell = Gtk::manage (new Gtk::CellRendererText());
316 cols_count = treeview_.append_column (M ("EXIFFILTER_APERTURE"), *cell);
317 col = treeview_.get_column (cols_count - 1);
318
319 if (col) {
320 col->set_cell_data_func (
321 *cell, sigc::mem_fun (
322 *this, &DynamicProfilePanel::render_fnumber));
323 }
324
325 cell = Gtk::manage (new Gtk::CellRendererText());
326 cols_count = treeview_.append_column (M ("EXIFFILTER_FOCALLEN"), *cell);
327 col = treeview_.get_column (cols_count - 1);
328
329 if (col) {
330 col->set_cell_data_func (
331 *cell, sigc::mem_fun (
332 *this, &DynamicProfilePanel::render_focallen));
333 }
334
335 cell = Gtk::manage (new Gtk::CellRendererText());
336 cols_count = treeview_.append_column (M ("EXIFFILTER_SHUTTER"), *cell);
337 col = treeview_.get_column (cols_count - 1);
338
339 if (col) {
340 col->set_cell_data_func (
341 *cell, sigc::mem_fun (
342 *this, &DynamicProfilePanel::render_shutterspeed));
343 }
344
345 cell = Gtk::manage (new Gtk::CellRendererText());
346 cols_count = treeview_.append_column (
347 M ("EXIFFILTER_EXPOSURECOMPENSATION"), *cell);
348 col = treeview_.get_column (cols_count - 1);
349
350 if (col) {
351 col->set_cell_data_func (
352 *cell, sigc::mem_fun (
353 *this, &DynamicProfilePanel::render_expcomp));
354 }
355
356 show_all_children();
357
358 for (auto &r : ProfileStore::getInstance()->getRules()) {
359 add_rule (r);
360 }
361 }
362
363
update_rule(Gtk::TreeModel::Row row,const DynamicProfileRule & rule)364 void DynamicProfilePanel::update_rule (Gtk::TreeModel::Row row,
365 const DynamicProfileRule &rule)
366 {
367 row[columns_.iso] = rule.iso;
368 row[columns_.fnumber] = rule.fnumber;
369 row[columns_.focallen] = rule.focallen;
370 row[columns_.shutterspeed] = rule.shutterspeed;
371 row[columns_.expcomp] = rule.expcomp;
372 row[columns_.camera] = rule.camera;
373 row[columns_.lens] = rule.lens;
374 row[columns_.imagetype] = rule.imagetype;
375 row[columns_.profilepath] = rule.profilepath;
376 }
377
add_rule(const DynamicProfileRule & rule)378 void DynamicProfilePanel::add_rule (const DynamicProfileRule &rule)
379 {
380 auto row = * (treemodel_->append());
381 update_rule (row, rule);
382 }
383
384
to_rule(Gtk::TreeModel::Row row,int serial)385 DynamicProfileRule DynamicProfilePanel::to_rule (Gtk::TreeModel::Row row,
386 int serial)
387 {
388 DynamicProfileRule ret;
389 ret.serial_number = serial;
390 ret.iso = row[columns_.iso];
391 ret.fnumber = row[columns_.fnumber];
392 ret.focallen = row[columns_.focallen];
393 ret.shutterspeed = row[columns_.shutterspeed];
394 ret.expcomp = row[columns_.expcomp];
395 ret.camera = row[columns_.camera];
396 ret.lens = row[columns_.lens];
397 ret.profilepath = row[columns_.profilepath];
398 ret.imagetype = row[columns_.imagetype];
399 return ret;
400 }
401
402
render_profilepath(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)403 void DynamicProfilePanel::render_profilepath (
404 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
405 {
406 auto row = *iter;
407 Gtk::CellRendererText *ct = static_cast<Gtk::CellRendererText *> (cell);
408 auto value = row[columns_.profilepath];
409 auto pse = ProfileStore::getInstance()->findEntryFromFullPath (value);
410
411 if (pse != nullptr) {
412 ct->property_text() = pse->label;
413 } else {
414 ct->property_text() = value;
415 }
416 }
417
418
419 #define RENDER_RANGE_(tp, name, tostr) \
420 auto row = *iter; \
421 Gtk::CellRendererText *ct = static_cast<Gtk::CellRendererText *>(cell); \
422 DynamicProfileRule::Range<tp> r = row[columns_. name]; \
423 DynamicProfileRule dflt; \
424 if (r.min > dflt.name.min || r.max < dflt.name.max) { \
425 auto value = tostr(r.min) + " - " + tostr(r.max); \
426 ct->property_text() = value; \
427 } else { \
428 ct->property_text() = ""; \
429 }
430
431
432 namespace
433 {
434
435 template <class V>
to_str(V n,int precision=1)436 Glib::ustring to_str (V n, int precision = 1)
437 {
438 std::ostringstream buf;
439 buf << std::setprecision (precision) << std::fixed << n;
440 return buf.str();
441 }
442
443 } // namespace
444
render_iso(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)445 void DynamicProfilePanel::render_iso (
446 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
447 {
448 RENDER_RANGE_ (int, iso, to_str);
449 }
450
451
render_fnumber(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)452 void DynamicProfilePanel::render_fnumber (
453 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
454 {
455 RENDER_RANGE_ (double, fnumber,
456 [] (double f) {
457 return std::string ("f/") +
458 rtengine::FramesMetaData::apertureToString (f);
459 });
460 }
461
462
render_focallen(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)463 void DynamicProfilePanel::render_focallen (
464 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
465 {
466 RENDER_RANGE_ (double, focallen, to_str);
467 }
468
469
render_shutterspeed(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)470 void DynamicProfilePanel::render_shutterspeed (
471 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
472 {
473 RENDER_RANGE_ (double, shutterspeed,
474 rtengine::FramesMetaData::shutterToString);
475 }
476
477
render_expcomp(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)478 void DynamicProfilePanel::render_expcomp (
479 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
480 {
481 RENDER_RANGE_ (double, expcomp, to_str);
482 }
483
484 #undef RENDER_RANGE_
485
486 #define RENDER_OPTIONAL_(name) \
487 auto row = *iter; \
488 Gtk::CellRendererText *ct = static_cast<Gtk::CellRendererText *>(cell); \
489 DynamicProfileRule::Optional o = row[columns_. name]; \
490 if (o.enabled) { \
491 ct->property_text() = o.value; \
492 } else { \
493 ct->property_text() = ""; \
494 }
495
render_camera(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)496 void DynamicProfilePanel::render_camera (
497 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
498 {
499 RENDER_OPTIONAL_ (camera);
500 }
501
502
render_lens(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)503 void DynamicProfilePanel::render_lens (
504 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
505 {
506 RENDER_OPTIONAL_ (lens);
507 }
508
render_imagetype(Gtk::CellRenderer * cell,const Gtk::TreeModel::iterator & iter)509 void DynamicProfilePanel::render_imagetype (
510 Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter)
511 {
512 auto row = *iter;
513 Gtk::CellRendererText *ct = static_cast<Gtk::CellRendererText *>(cell);
514 DynamicProfileRule::Optional o = row[columns_.imagetype];
515 if (o.enabled) {
516 ct->property_text() = M(std::string("DYNPROFILEEDITOR_IMGTYPE_") + o.value);
517 } else { \
518 ct->property_text() = "";
519 }
520 }
521
522 #undef RENDER_OPTIONAL_
523
on_button_up()524 void DynamicProfilePanel::on_button_up()
525 {
526 auto s = treeview_.get_selection();
527
528 if (!s->count_selected_rows()) {
529 return;
530 }
531
532 auto it = s->get_selected();
533
534 if (it != treemodel_->children().begin()) {
535 auto it2 = it;
536 --it2;
537 treemodel_->iter_swap (it, it2);
538 }
539 }
540
on_button_down()541 void DynamicProfilePanel::on_button_down()
542 {
543 auto s = treeview_.get_selection();
544
545 if (!s->count_selected_rows()) {
546 return;
547 }
548
549 auto it = s->get_selected();
550 auto it2 = it;
551 ++it2;
552
553 if (it2 != treemodel_->children().end()) {
554 treemodel_->iter_swap (it, it2);
555 }
556 }
557
558
on_button_delete()559 void DynamicProfilePanel::on_button_delete()
560 {
561 auto s = treeview_.get_selection();
562
563 if (!s->count_selected_rows()) {
564 return;
565 }
566
567 auto it = s->get_selected();
568 treemodel_->erase (it);
569 }
570
571
on_button_new()572 void DynamicProfilePanel::on_button_new()
573 {
574 EditDialog d (M ("DYNPROFILEEDITOR_NEW_RULE"),
575 static_cast<Gtk::Window &> (*get_toplevel()));
576 int status = d.run();
577
578 if (status == 1) {
579 DynamicProfileRule rule = d.get_rule();
580 add_rule (rule);
581 }
582 }
583
584
on_button_edit()585 void DynamicProfilePanel::on_button_edit()
586 {
587 auto s = treeview_.get_selection();
588
589 if (!s->count_selected_rows()) {
590 return;
591 }
592
593 EditDialog d (M ("DYNPROFILEEDITOR_EDIT_RULE"),
594 static_cast<Gtk::Window &> (*get_toplevel()));
595 Gtk::TreeModel::Row row = * (s->get_selected());
596 d.set_rule (to_rule (row));
597 int status = d.run();
598
599 if (status == 1) {
600 update_rule (row, d.get_rule());
601 }
602 }
603
604
save()605 void DynamicProfilePanel::save()
606 {
607 std::vector<DynamicProfileRule> rules;
608 int serial = 1;
609
610 for (auto row : treemodel_->children()) {
611 rules.emplace_back (to_rule (row, serial++));
612 }
613
614 ProfileStore::getInstance()->setRules (rules);
615
616 if (!ProfileStore::getInstance()->storeRules()) {
617 printf ("Error in saving dynamic profile rules\n");
618 } else if (options.rtSettings.verbose) {
619 printf ("Saved %d dynamic profile rules\n", int (rules.size()));
620 }
621 }
622