diff --git a/rtdata/images/svg/add.svg b/rtdata/images/svg/add.svg index c45f9f584..41fa7cc39 100644 --- a/rtdata/images/svg/add.svg +++ b/rtdata/images/svg/add.svg @@ -17,7 +17,7 @@ inkscape:export-filename="/tmp/template.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" - inkscape:version="0.92.2 2405546, 2018-03-11" + inkscape:version="0.91 r13725" sodipodi:docname="add.svg"> image/svg+xml - + Maciej Dworak @@ -120,8 +120,8 @@ style="opacity:0.7;fill:none;fill-opacity:0.53333285;fill-rule:nonzero;stroke:#2a7fff;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" /> diff --git a/rtdata/images/svg/box.svg b/rtdata/images/svg/box.svg new file mode 100644 index 000000000..2ebee4b8c --- /dev/null +++ b/rtdata/images/svg/box.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + image/svg+xml + + + + + Maciej Dworak + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + diff --git a/rtdata/images/svg/tick.svg b/rtdata/images/svg/tick.svg index 8ab7a2e27..dd4ab4bdd 100644 --- a/rtdata/images/svg/tick.svg +++ b/rtdata/images/svg/tick.svg @@ -17,8 +17,8 @@ inkscape:export-filename="/tmp/template.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" - inkscape:version="0.92.2 2405546, 2018-03-11" - sodipodi:docname="tick-large.svg"> + inkscape:version="0.91 r13725" + sodipodi:docname="tick.svg"> image/svg+xml - + Maciej Dworak @@ -103,7 +103,7 @@ sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0" id="path2996-6" - d="M 4.6666624,10.166665 8.3333305,13.833335 19.333336,2.833329 23.000006,6.4999972 8.3333305,21.166671 0.99999442,13.833335 Z" + d="M 6.0000005,10.299997 9.0000007,13.533332 18.000004,3.833329 21.000006,7.066663 9.0000007,20 3,13.533332 Z" style="opacity:0.7;fill:#2a7fff;fill-opacity:1;stroke:none;stroke-width:2.30911016" /> diff --git a/rtengine/metadata.cc b/rtengine/metadata.cc index e2bc4dc42..af2a7ef8a 100644 --- a/rtengine/metadata.cc +++ b/rtengine/metadata.cc @@ -313,6 +313,8 @@ void Exiv2Metadata::remove_unwanted(Exiv2::ExifData &dst) const for (auto it = dst.begin(); it != dst.end(); ) { if (badtags.find(it->key()) != badtags.end()) { it = dst.erase(it); + } else if (exif_keys_ && exif_keys_->find(it->key()) == exif_keys_->end()) { + it = dst.erase(it); } else { bool found = false; for (auto &p : badpatterns) { @@ -393,6 +395,16 @@ void Exiv2Metadata::saveToXmp(const Glib::ustring &path) const } +void Exiv2Metadata::setExifKeys(const std::vector *keys) +{ + exif_keys_.reset(); + if (keys) { + exif_keys_ = std::make_shared>(); + exif_keys_->insert(keys->begin(), keys->end()); + } +} + + Glib::ustring Exiv2Metadata::xmpSidecarPath(const Glib::ustring &path) { Glib::ustring fn = path; diff --git a/rtengine/metadata.h b/rtengine/metadata.h index 7439d6b36..57484d234 100644 --- a/rtengine/metadata.h +++ b/rtengine/metadata.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "procparams.h" #include "cache.h" @@ -55,6 +56,8 @@ public: void saveToImage(const Glib::ustring& path) const; void saveToXmp(const Glib::ustring& path) const; + void setExifKeys(const std::vector *keys); + static Glib::ustring xmpSidecarPath(const Glib::ustring& path); static Exiv2::XmpData getXmpSidecar(const Glib::ustring& path); @@ -76,6 +79,8 @@ private: Exiv2::IptcData iptc_data_; Exiv2::XmpData xmp_data_; + std::shared_ptr> exif_keys_; + typedef std::pair, Glib::TimeVal> CacheVal; typedef Cache ImageCache; static std::unique_ptr cache_; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f3068c18e..5076e147f 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -178,6 +178,17 @@ void getFromKeyfile( } } +void getFromKeyfile( + const Glib::KeyFile& keyfile, + const Glib::ustring& group_name, + const Glib::ustring& key, + std::vector& value +) +{ + auto tmpval = keyfile.get_string_list(group_name, key); + value.assign(tmpval.begin(), tmpval.end()); +} + template bool assignFromKeyfile( const Glib::KeyFile& keyfile, @@ -306,6 +317,17 @@ void putToKeyfile( keyfile.set_double_list(group_name, key, list); } +void putToKeyfile( + const Glib::ustring& group_name, + const Glib::ustring& key, + const std::vector& value, + Glib::KeyFile& keyfile +) +{ + const Glib::ArrayHandle list = value; + keyfile.set_string_list(group_name, key, list); +} + void putToKeyfile( const Glib::ustring& group_name, const Glib::ustring& key, @@ -5226,13 +5248,15 @@ Glib::ustring RAWParams::getFlatFieldBlurTypeString(FlatFieldBlurType type) MetaDataParams::MetaDataParams(): - mode(MetaDataParams::TUNNEL) + mode(MetaDataParams::TUNNEL), + exifKeys{"ALL"} { } bool MetaDataParams::operator==(const MetaDataParams &other) const { - return mode == other.mode; + return mode == other.mode + && exifKeys == other.exifKeys; } bool MetaDataParams::operator!=(const MetaDataParams &other) const @@ -6823,6 +6847,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // MetaData saveToKeyfile(!pedited || pedited->metadata.mode, "MetaData", "Mode", metadata.mode, keyFile); + saveToKeyfile(!pedited || pedited->metadata.exifKeys, "MetaData", "ExifKeys", metadata.exifKeys, keyFile); // Film negative saveToKeyfile(!pedited || pedited->filmNegative.enabled, "Film Negative", "Enabled", filmNegative.enabled, keyFile); @@ -9350,6 +9375,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (mode >= int(MetaDataParams::TUNNEL) && mode <= int(MetaDataParams::STRIP)) { metadata.mode = static_cast(mode); } + + assignFromKeyfile(keyFile, "MetaData", "ExifKeys", pedited, metadata.exifKeys, pedited->metadata.exifKeys); } if (keyFile.has_group("Exif")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 4a1eb47e3..dd6872630 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1728,6 +1728,7 @@ struct MetaDataParams { STRIP }; Mode mode; + std::vector exifKeys; MetaDataParams(); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 0b6406b62..c8ee5e147 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1739,6 +1739,9 @@ private: case MetaDataParams::EDIT: info.setExif(params.exif); info.setIptc(params.iptc); + if (!(params.metadata.exifKeys.size() == 1 && params.metadata.exifKeys[0] == "ALL")) { + info.setExifKeys(&(params.metadata.exifKeys)); + } readyImg->setMetadata(std::move(info)); break; default: // case MetaDataParams::STRIP diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 5b93f25c8..f63541e5f 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -51,16 +51,17 @@ ExifPanel::ExifPanel() : exifTree->set_rules_hint (false); exifTree->set_reorderable (false); exifTree->set_enable_search (false); - exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - scrolledWindow->set_shadow_type (Gtk::SHADOW_NONE); - scrolledWindow->set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); + exifTree->get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE); + scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); scrolledWindow->property_window_placement().set_value (Gtk::CORNER_TOP_LEFT); - scrolledWindow->add (*exifTree); + scrolledWindow->add(*exifTree); - exifTreeModel = Gtk::TreeStore::create (exifColumns); - exifTree->set_model (exifTreeModel); - exifTree->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_NONE); + exifTreeModel = Gtk::TreeStore::create(exifColumns); + exifTree->set_model(exifTreeModel); + exifTree->set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_NONE); exifTree->set_show_expanders(false); + exifTree->set_tooltip_column(0); keepicon = RTImage::createPixbufFromFile ("tick-small.png"); editicon = RTImage::createPixbufFromFile("add-small.png"); @@ -69,25 +70,32 @@ ExifPanel::ExifPanel() : Gtk::CellRendererPixbuf* render_pb = Gtk::manage (new Gtk::CellRendererPixbuf ()); Gtk::CellRendererText *render_txt = Gtk::manage (new Gtk::CellRendererText()); render_txt->property_ellipsize() = Pango::ELLIPSIZE_END; - viewcol->pack_start (*render_pb, false); - viewcol->pack_start (*render_txt, true); - viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon); - viewcol->add_attribute (*render_txt, "markup", exifColumns.label); - viewcol->set_expand (true); - viewcol->set_resizable (true); - viewcol->set_fixed_width (35); - viewcol->set_min_width (35); - viewcol->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + viewcol->pack_start(*render_pb, false); + viewcol->pack_start(*render_txt, true); + viewcol->add_attribute(*render_pb, "pixbuf", exifColumns.icon); + viewcol->add_attribute(*render_txt, "markup", exifColumns.label); + viewcol->set_expand(true); + viewcol->set_resizable(true); + viewcol->set_fixed_width(35); + viewcol->set_min_width(35); + viewcol->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); render_pb->property_ypad() = 0; render_txt->property_ypad() = 0; render_pb->property_yalign() = 0; render_txt->property_yalign() = 0; - exifTree->append_column (*viewcol); + exif_active_renderer_.property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; + exif_active_renderer_.signal_toggled().connect(sigc::mem_fun(this, &ExifPanel::onKeyActiveToggled)); + exif_active_column_.pack_start(exif_active_renderer_); + exif_active_column_.set_cell_data_func(exif_active_renderer_, sigc::mem_fun(this, &ExifPanel::setKeyActive)); - Gtk::TreeView::Column *viewcolv = Gtk::manage (new Gtk::TreeView::Column ("Value")); - Gtk::CellRendererText *render_txtv = Gtk::manage (new Gtk::CellRendererText()); + exifTree->append_column(exif_active_column_); + + exifTree->append_column(*viewcol); + + Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value")); + Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText()); render_txtv->property_ellipsize() = Pango::ELLIPSIZE_END; viewcolv->pack_start (*render_txtv, true); viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value); @@ -108,26 +116,23 @@ ExifPanel::ExifPanel() : buttons1->set_column_homogeneous (true); setExpandAlignProperties (buttons1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - add = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT") - add->set_image (*Gtk::manage (new RTImage(editicon))); - add->set_tooltip_text (M ("EXIFPANEL_ADDEDITHINT")); - add->get_style_context()->add_class ("Right"); - setExpandAlignProperties (add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to (*add, Gtk::POS_RIGHT, 1, 1); + const auto addbtn = + [&](const Glib::ustring &tip, const Glib::ustring &icon1, const Glib::ustring &icon2=Glib::ustring()) -> Gtk::Button * + { + Gtk::Button *b = Gtk::manage(new Gtk::Button()); + b->set_image(*Gtk::manage(new RTImage(icon1, icon2))); + b->set_tooltip_text(M(tip)); + b->get_style_context()->add_class("Right"); + setExpandAlignProperties(b, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to(*b, Gtk::POS_RIGHT, 1, 1); + return b; + }; - reset = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESET") - reset->set_image (*Gtk::manage (new RTImage("undo.png", "redo.png"))); - reset->set_tooltip_text (M ("EXIFPANEL_RESETHINT")); - reset->get_style_context()->add_class ("MiddleH"); - setExpandAlignProperties (reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to (*reset, Gtk::POS_RIGHT, 1, 1); - - resetAll = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESETALL") - resetAll->set_image (*Gtk::manage (new RTImage ("undo-all.png", "redo-all.png"))); - resetAll->set_tooltip_text (M ("EXIFPANEL_RESETALLHINT")); - resetAll->get_style_context()->add_class ("Right"); - setExpandAlignProperties (resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to (*resetAll, Gtk::POS_RIGHT, 1, 1); + activate_all_ = addbtn("EXIFPANEL_ACTIVATE_ALL_HINT", "tick.png"); + activate_none_ = addbtn("EXIFPANEL_ACTIVATE_NONE_HINT", "box.png"); + add = addbtn("EXIFPANEL_ADDEDIT", "add.png"); + reset = addbtn("EXIFPANEL_RESETHINT", "undo.png", "redo.png"); + resetAll = addbtn("EXIFPANEL_RESETALLHINT", "undo-all.png", "redo-all.png"); pack_end (*buttons1, Gtk::PACK_SHRINK); @@ -137,6 +142,8 @@ ExifPanel::ExifPanel() : reset->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetPressed) ); resetAll->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetAllPressed) ); add->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::addPressed) ); + activate_all_->signal_clicked().connect(sigc::mem_fun(*this, &ExifPanel::activateAllPressed)); + activate_none_->signal_clicked().connect(sigc::mem_fun(*this, &ExifPanel::activateNonePressed)); show_all (); } @@ -147,24 +154,56 @@ ExifPanel::~ExifPanel () void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener(); *changeList = pp->exif; - setImageData (idata); + initial_active_keys_.clear(); + initial_active_keys_.insert(pp->metadata.exifKeys.begin(), pp->metadata.exifKeys.end()); + cur_active_keys_ = initial_active_keys_; + setImageData(idata); refreshTags(); - enableListener (); + enableListener(); } void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited) { pp->exif = *changeList; + + std::unordered_set prev; + bool all_active = (cur_active_keys_.size() == 1 && *(cur_active_keys_.begin()) == "ALL"); + + if (!all_active) { + prev = cur_active_keys_; + } + + pp->metadata.exifKeys.clear(); + + bool none_active = true; + + auto root = exifTreeModel->children(); + for (auto &entry : root->children()) { + Glib::ustring key = entry[exifColumns.key]; + prev.erase(key); + if (entry[exifColumns.active]) { + pp->metadata.exifKeys.push_back(key); + none_active = false; + } else { + all_active = false; + } + } + + if (all_active) { + pp->metadata.exifKeys = { "ALL" }; + } else if (!none_active) { + pp->metadata.exifKeys.insert(pp->metadata.exifKeys.end(), prev.begin(), prev.end()); + } + std::sort(pp->metadata.exifKeys.begin(), pp->metadata.exifKeys.end()); } void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { - *defChangeList = defParams->exif; } @@ -195,6 +234,9 @@ void ExifPanel::addTag(const std::string &key, const Glib::ustring &label, const row[exifColumns.label] = escapeHtmlChars(label); row[exifColumns.value] = escapeHtmlChars(value); + bool active = (cur_active_keys_.size() == 1 && *(cur_active_keys_.begin()) == "ALL") || cur_active_keys_.find(key) != cur_active_keys_.end(); + row[exifColumns.active] = active; + if (edited) { row[exifColumns.icon] = editicon; } else if (editable) { @@ -223,6 +265,17 @@ void ExifPanel::refreshTags() ed.insert(p.first); } + const auto to_label = + [](const Exiv2::Exifdatum &tag) -> Glib::ustring + { + auto s = tag.key(); + auto pos = s.find('.'); + if (pos != std::string::npos) { + s = s.substr(pos+1); + } + return s; + }; + try { rtengine::Exiv2Metadata meta(fn); meta.load(); @@ -239,10 +292,10 @@ void ExifPanel::refreshTags() const auto pos = exif.findKey(Exiv2::ExifKey(p.first)); if (pos != exif.end() && pos->size()) { const bool edited = changeList->find(pos->key()) != changeList->end(); - addTag(pos->key(), pos->tagLabel(), pos->print(&exif), true, edited); + addTag(pos->key(), to_label(*pos), pos->print(&exif), true, edited); } } - std::map keymap; + std::multimap keymap; for (const auto& tag : exif) { const bool editable = ed.find(tag.key()) != ed.end(); if ( @@ -254,16 +307,16 @@ void ExifPanel::refreshTags() || tag.size() < 256 ) ) { - std::string lbl = tag.tagLabel(); + std::string lbl = to_label(tag); for (auto &c : lbl) { c = std::tolower(c); } - keymap[lbl] = tag.key(); + keymap.insert(std::make_pair(lbl, tag.key())); } } for (auto &p : keymap) { auto &tag = *(exif.findKey(Exiv2::ExifKey(p.second))); - addTag(tag.key(), tag.tagLabel(), tag.print(&exif), false, false); + addTag(tag.key(), to_label(tag), tag.print(&exif), false, false); } } catch (const std::exception& exc) { return; @@ -303,7 +356,7 @@ void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter) changeList->erase(key); } -void ExifPanel::resetPressed () +void ExifPanel::resetPressed() { std::vector sel = exifTree->get_selection()->get_selected_rows(); @@ -320,8 +373,9 @@ void ExifPanel::resetAllPressed () { setImageData(idata); *changeList = *defChangeList; + cur_active_keys_ = initial_active_keys_; refreshTags(); - notifyListener (); + notifyListener(); } void ExifPanel::addPressed () @@ -391,8 +445,9 @@ void ExifPanel::addPressed () auto key = editableTags[tcombo->get_active_row_number()].first; const auto value = ventry->get_text(); (*changeList)[key] = value; + cur_active_keys_.insert(key); refreshTags(); - notifyListener (); + notifyListener(); } delete dialog; @@ -404,9 +459,52 @@ void ExifPanel::addPressed () delete hb2; } -void ExifPanel::notifyListener () +void ExifPanel::activateAllPressed() +{ + disableListener(); + auto root = exifTreeModel->children(); + for (auto &row : root->children()) { + row[exifColumns.active] = true; + } + enableListener(); + notifyListener(); +} + + +void ExifPanel::activateNonePressed() +{ + disableListener(); + auto root = exifTreeModel->children(); + for (auto &row : root->children()) { + row[exifColumns.active] = false; + } + enableListener(); + notifyListener(); +} + + +void ExifPanel::notifyListener() { if (listener) { - listener->panelChanged (EvExif, M ("HISTORY_CHANGED")); + listener->panelChanged(EvExif, M("HISTORY_CHANGED")); } } + + +void ExifPanel::onKeyActiveToggled(const Glib::ustring &path) +{ + auto it = exifTreeModel->get_iter(path); + if (it) { + auto row = *it; + row[exifColumns.active] = !row[exifColumns.active]; + notifyListener(); + } +} + + +void ExifPanel::setKeyActive(Gtk::CellRenderer *renderer, const Gtk::TreeModel::iterator &it) +{ + auto row = *it; + static_cast(renderer)->set_active(row[exifColumns.active]); +} + diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index cfcf77e4d..1f9378fa3 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -21,6 +21,7 @@ #include #include +#include #include "toolpanel.h" @@ -56,6 +57,7 @@ private: Gtk::TreeModelColumn value_nopango; Gtk::TreeModelColumn editable; Gtk::TreeModelColumn edited; + Gtk::TreeModelColumn active; ExifColumns() { @@ -66,6 +68,7 @@ private: add(edited); add(value_nopango); add(editable); + add(active); } }; Glib::RefPtr keepicon; @@ -79,15 +82,29 @@ private: Gtk::Button* add; Gtk::Button* reset; Gtk::Button* resetAll; + Gtk::Button *activate_all_; + Gtk::Button *activate_none_; + + Gtk::CellRendererToggle exif_active_renderer_; + Gtk::TreeView::Column exif_active_column_; const std::vector> editableTags; + std::unordered_set initial_active_keys_; + std::unordered_set cur_active_keys_; + void addTag(const std::string &key, const Glib::ustring &label, const Glib::ustring &value, bool editable, bool edited); void refreshTags(); void resetIt(const Gtk::TreeModel::const_iterator& iter); void resetPressed(); void resetAllPressed(); void addPressed(); + void activateAllPressed(); + void activateNonePressed(); + + void setKeyActive(Gtk::CellRenderer *renderer, const Gtk::TreeModel::iterator &it); + void onKeyActiveToggled(const Glib::ustring &path); + public: ExifPanel (); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 1fdefc0a3..8459d4013 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -675,6 +675,7 @@ void ParamsEdited::set(bool v) dehaze.depth = v; dehaze.saturation = v; metadata.mode = v; + metadata.exifKeys = v; filmNegative.enabled = v; filmNegative.redRatio = v; filmNegative.greenExp = v; @@ -1931,6 +1932,7 @@ void ParamsEdited::initFrom(const std::vector& dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; dehaze.saturation = dehaze.saturation && p.dehaze.saturation == other.dehaze.saturation; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; + metadata.exifKeys = metadata.exifKeys && p.metadata.exifKeys == other.metadata.exifKeys; filmNegative.enabled = filmNegative.enabled && p.filmNegative.enabled == other.filmNegative.enabled; filmNegative.redRatio = filmNegative.redRatio && p.filmNegative.redRatio == other.filmNegative.redRatio; filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp; @@ -6569,6 +6571,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.metadata.mode = mods.metadata.mode; } + if (metadata.exifKeys) { + toEdit.metadata.exifKeys = mods.metadata.exifKeys; + } + if (filmNegative.enabled) { toEdit.filmNegative.enabled = mods.filmNegative.enabled; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 95fc76407..a7306ba68 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1361,6 +1361,7 @@ struct RAWParamsEdited { struct MetaDataParamsEdited { bool mode; + bool exifKeys; }; struct FilmNegativeParamsEdited {