diff --git a/rtdata/languages/default b/rtdata/languages/default index 9ff1e119c..017554bff 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2214,7 +2214,7 @@ TP_LOCALLAB_TONEMAPESTOP_TOOLTIP;Increase Edge stopping - or Reweighting iterate TP_LOCALLAB_VIBRANCE;Vibrance TP_LOCALLAB_WARM;Warm - Cool & Color artifacts TP_LOCALLAB_WARM_TOOLTIP;This slider use Ciecam algorithm and acts as White Balance, it can warm or cool the area selected.\nIt can also in some cases reduce color artifacts. -TP_LOCALLAB_SPOTNAME;Control Spot # +TP_LOCALLAB_SPOTNAME;New Spot TP_LOCALLAB_BUTTON_ADD;Add TP_LOCALLAB_BUTTON_DEL;Delete TP_LOCALLAB_BUTTON_DUPL;Duplicate diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 5a181618a..751bf1892 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -948,7 +948,7 @@ void Crop::update(int todo) // int maxspot = 1; if (needslocal) { - for (int sp = 0; sp < params.locallab.nbspot && sp < (int)params.locallab.spots.size(); sp++) { + for (int sp = 0; sp < (int)params.locallab.spots.size(); sp++) { locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve); loclhCurve.Set(params.locallab.spots.at(sp).LHcurve, LHutili); lochhCurve.Set(params.locallab.spots.at(sp).HHcurve, HHutili); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6c30e6d35..da687567a 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -882,7 +882,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) float avge; std::vector locallref; - for (int sp = 0; sp < params->locallab.nbspot && sp < (int)params->locallab.spots.size(); sp++) { + for (size_t sp = 0; sp < params->locallab.spots.size(); sp++) { // Set local curves of current spot to LUT LHutili = false; HHutili = false; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 8cc2da873..d91385171 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2336,7 +2336,6 @@ void WaveletParams::getCurves( LocallabParams::LocallabSpot::LocallabSpot() : // Control spot settings - id(1), name(""), isvisible(true), shape("ELI"), @@ -2585,8 +2584,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const { return // Control spot settings - id == other.id - && name == other.name + name == other.name && isvisible == other.isvisible && shape == other.shape && spotMethod == other.spotMethod @@ -2855,7 +2853,6 @@ const std::vector LocallabParams::DEF_LC_CURVE = {(double)FCT_MinMaxCPoi LocallabParams::LocallabParams() : enabled(false), - nbspot(0), selspot(0), spots() { @@ -2865,7 +2862,6 @@ bool LocallabParams::operator ==(const LocallabParams& other) const { return enabled == other.enabled - && nbspot == other.nbspot && selspot == other.selspot && spots == other.spots; } @@ -3814,14 +3810,12 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Locallab saveToKeyfile(!pedited || pedited->locallab.enabled, "Locallab", "Enabled", locallab.enabled, keyFile); - saveToKeyfile(!pedited || pedited->locallab.nbspot, "Locallab", "Nbspot", locallab.nbspot, keyFile); saveToKeyfile(!pedited || pedited->locallab.selspot, "Locallab", "Selspot", locallab.selspot, keyFile); - for (int i = 0; i < locallab.nbspot && i < (int)locallab.spots.size(); i++) { - if (!pedited || i < (int)pedited->locallab.spots.size()) { + for (size_t i = 0; i < locallab.spots.size(); i++) { + if (!pedited || i < pedited->locallab.spots.size()) { const LocallabParams::LocallabSpot& spot = locallab.spots.at(i); // Control spot settings - saveToKeyfile(!pedited || pedited->locallab.id, "Locallab", "Id_" + std::to_string(i), spot.id, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).name, "Locallab", "Name_" + std::to_string(i), spot.name, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).isvisible, "Locallab", "Isvisible_" + std::to_string(i), spot.isvisible, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shape, "Locallab", "Shape_" + std::to_string(i), spot.shape, keyFile); @@ -5154,27 +5148,20 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Locallab")) { assignFromKeyfile(keyFile, "Locallab", "Enabled", pedited, locallab.enabled, pedited->locallab.enabled); - assignFromKeyfile(keyFile, "Locallab", "Nbspot", pedited, locallab.nbspot, pedited->locallab.nbspot); assignFromKeyfile(keyFile, "Locallab", "Selspot", pedited, locallab.selspot, pedited->locallab.selspot); - // Resize locallab settings if required - if (locallab.nbspot > (int)locallab.spots.size()) { - locallab.spots.resize(locallab.nbspot); - } + Glib::ustring ppName; + bool peName; + int i = 0; - // Initialize LocallabSpotEdited to false according to nbspot - if (pedited) { - pedited->locallab.spots.clear(); - pedited->locallab.spots.resize(locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(false)); - } - - for (int i = 0; i < locallab.nbspot; i++) { + while (assignFromKeyfile(keyFile, "Locallab", "Name_" + std::to_string(i), pedited, ppName, peName)) { + // Create new LocallabSpot and LocallabParamsEdited LocallabParams::LocallabSpot spot; + spot.name = ppName; LocallabParamsEdited::LocallabSpotEdited spotEdited(false); + spotEdited.name = peName; // Control spot settings - assignFromKeyfile(keyFile, "Locallab", "Id_" + std::to_string(i), pedited, spot.id, pedited->locallab.id); - assignFromKeyfile(keyFile, "Locallab", "Name_" + std::to_string(i), pedited, spot.name, spotEdited.name); assignFromKeyfile(keyFile, "Locallab", "Isvisible_" + std::to_string(i), pedited, spot.isvisible, spotEdited.isvisible); assignFromKeyfile(keyFile, "Locallab", "Shape_" + std::to_string(i), pedited, spot.shape, spotEdited.shape); assignFromKeyfile(keyFile, "Locallab", "SpotMethod_" + std::to_string(i), pedited, spot.spotMethod, spotEdited.spotMethod); @@ -5479,15 +5466,18 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Bilateral_" + std::to_string(i), pedited, spot.bilateral, spotEdited.bilateral); assignFromKeyfile(keyFile, "Locallab", "Sensiden_" + std::to_string(i), pedited, spot.sensiden, spotEdited.sensiden); - locallab.spots.at(i) = spot; + // Append LocallabSpot and LocallabParamsEdited + locallab.spots.push_back(spot); if (pedited) { - pedited->locallab.spots.at(i) = spotEdited; + pedited->locallab.spots.push_back(spotEdited); } + + // Update increment + i++; } } - if (keyFile.has_group("PCVignette")) { assignFromKeyfile(keyFile, "PCVignette", "Enabled", pedited, pcvignette.enabled, pedited->pcvignette.enabled); assignFromKeyfile(keyFile, "PCVignette", "Strength", pedited, pcvignette.strength, pedited->pcvignette.strength); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 5b23b12a8..796cdf6dc 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -935,7 +935,6 @@ struct GradientParams { struct LocallabParams { struct LocallabSpot { // Control spot settings - int id; Glib::ustring name; bool isvisible; Glib::ustring shape; // ELI, RECT @@ -1185,7 +1184,6 @@ struct LocallabParams { bool operator !=(const LocallabSpot& other) const; }; - bool enabled; static const double LABGRIDL_CORR_MAX; static const double LABGRIDL_CORR_SCALE; static const double LABGRIDL_DIRECT_SCALE; @@ -1195,7 +1193,8 @@ struct LocallabParams { static const std::vector DEF_EXP_CURVE; static const std::vector DEF_RET_CURVE; static const std::vector DEF_LC_CURVE; - int nbspot; + + bool enabled; int selspot; std::vector spots; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index e14cc47b3..dd9be7d03 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1121,7 +1121,7 @@ private: // int maxspot = 1; float** shbuffer = nullptr; - for (int sp = 0; sp < params.locallab.nbspot && sp < (int)params.locallab.spots.size(); sp++) { + for (size_t sp = 0; sp < params.locallab.spots.size(); sp++) { if (params.locallab.spots.at(sp).inverssha) { shbuffer = new float*[fh]; diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc index 6ea63ed77..5423be38f 100644 --- a/rtgui/controlspotpanel.cc +++ b/rtgui/controlspotpanel.cc @@ -125,19 +125,9 @@ ControlSpotPanel::ControlSpotPanel(): *this, &ControlSpotPanel::blockTreeviewSearch), false); auto cell = Gtk::manage(new Gtk::CellRendererText()); - int cols_count = treeview_->append_column("ID", *cell); + int cols_count = treeview_->append_column(M("TP_LOCALLAB_COL_NAME"), *cell); auto col = treeview_->get_column(cols_count - 1); - if (col) { - col->set_cell_data_func( - *cell, sigc::mem_fun( - *this, &ControlSpotPanel::render_id)); - } - - cell = Gtk::manage(new Gtk::CellRendererText()); - cols_count = treeview_->append_column(M("TP_LOCALLAB_COL_NAME"), *cell); - col = treeview_->get_column(cols_count - 1); - if (col) { col->set_cell_data_func( *cell, sigc::mem_fun( @@ -357,24 +347,6 @@ void ControlSpotPanel::setEditProvider(EditDataProvider* provider) EditSubscriber::setEditProvider(provider); } -void ControlSpotPanel::render_id( - Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter) -{ - auto row = *iter; - Gtk::CellRendererText *ct = static_cast(cell); - - // Render cell text - ct->property_text() = std::to_string(row[spots_.id]); - - // Render cell background color - if (row[spots_.mouseover]) { - ct->property_background_rgba() = colorMouseovertext; - } else { - ct->property_background_rgba() = colorNominal; - } - -} - void ControlSpotPanel::render_name( Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter) { @@ -425,8 +397,7 @@ void ControlSpotPanel::on_button_add() nbSpotChanged_ = true; selSpotChanged_ = true; eventType = SpotCreation; - const int newId = getNewId(); - listener->panelChanged(EvLocallabSpotCreated, "ID#" + std::to_string(newId)); + listener->panelChanged(EvLocallabSpotCreated, "-"); } void ControlSpotPanel::on_button_delete() @@ -441,8 +412,8 @@ void ControlSpotPanel::on_button_delete() nbSpotChanged_ = true; selSpotChanged_ = true; eventType = SpotDeletion; - const int delId = getSelectedSpot(); - listener->panelChanged(EvLocallabSpotDeleted, "ID#" + std::to_string(delId)); + SpotRow* const delSpotRow = getSpot(getSelectedSpot()); + listener->panelChanged(EvLocallabSpotDeleted, delSpotRow->name); } void ControlSpotPanel::on_button_duplicate() @@ -463,10 +434,9 @@ void ControlSpotPanel::on_button_duplicate() nbSpotChanged_ = true; selSpotChanged_ = true; eventType = SpotDuplication; - const int newId = getNewId(); - listener->panelChanged(EvLocallabSpotCreated, "ID#" + std::to_string(newId) - + " (" + M("TP_LOCALLAB_EV_DUPL") + " ID#" - + std::to_string(selId) + ")"); + SpotRow* const duplSpotRow = getSpot(getSelectedSpot()); + listener->panelChanged(EvLocallabSpotCreated, M("TP_LOCALLAB_EV_DUPL") + " " + + duplSpotRow->name); } void ControlSpotPanel::on_button_rename() @@ -558,12 +528,12 @@ bool ControlSpotPanel::on_button_visibility(GdkEventButton* event) // Raise event visibilityChanged_ = true; - const int id = getSelectedSpot(); + SpotRow* const spotRow = getSpot(getSelectedSpot()); if (row[spots_.isvisible]) { - listener->panelChanged(EvLocallabSpotVisibility, M("TP_LOCALLAB_EV_VIS") + " ID#" + std::to_string(id)); + listener->panelChanged(EvLocallabSpotVisibility, M("TP_LOCALLAB_EV_VIS") + " (" + spotRow->name + ")"); } else { - listener->panelChanged(EvLocallabSpotVisibility, M("TP_LOCALLAB_EV_NVIS") + " ID#" + std::to_string(id)); + listener->panelChanged(EvLocallabSpotVisibility, M("TP_LOCALLAB_EV_NVIS") + " (" + spotRow->name + ")"); } return true; @@ -637,13 +607,13 @@ void ControlSpotPanel::controlspotChanged() // Raise event selSpotChanged_ = true; eventType = SpotSelection; - const int selId = getSelectedSpot(); + SpotRow* const spotRow = getSpot(getSelectedSpot()); // Image area shall be regenerated if mask preview was active when switching spot if (maskPrevActive) { - listener->panelChanged(EvLocallabSpotSelectedWithMask, "ID#" + std::to_string(selId)); + listener->panelChanged(EvLocallabSpotSelectedWithMask, spotRow->name); } else { - listener->panelChanged(EvLocallabSpotSelected, "ID#" + std::to_string(selId)); + listener->panelChanged(EvLocallabSpotSelected, spotRow->name); } } @@ -1732,21 +1702,20 @@ int ControlSpotPanel::getEventType() return tmp; } -ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int id) +ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int index) { - // printf("getSpot: %d\n", id); + // printf("getSpot: %d\n", index); MyMutex::MyLock lock(mTreeview); SpotRow* r = new SpotRow(); - const Gtk::TreeModel::Children children = treemodel_->children(); + int i = -1; - for (auto iter = children.begin(); iter != children.end(); iter++) { - const Gtk::TreeModel::Row row = *iter; + for (auto &row : treemodel_->children()) { + i++; - if (row[spots_.id] == id) { - r->id = row[spots_.id]; + if (i == index) { r->name = row[spots_.name]; r->isvisible = row[spots_.isvisible]; r->shape = row[spots_.shape]; @@ -1778,20 +1747,11 @@ ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int id) return nullptr; } -std::vector* ControlSpotPanel::getSpotIdList() +int ControlSpotPanel::getSpotNumber() { - MyMutex::MyLock lock(mTreeview); + // printf("getSpotNumber\n"); - std::vector* r = new std::vector(); - - const Gtk::TreeModel::Children children = treemodel_->children(); - - for (auto iter = children.begin(); iter != children.end(); iter++) { - const Gtk::TreeModel::Row row = *iter; - r->push_back(row[spots_.id]); - } - - return r; + return (int)treemodel_->children().size(); } int ControlSpotPanel::getSelectedSpot() @@ -1804,28 +1764,37 @@ int ControlSpotPanel::getSelectedSpot() // Check if treeview has row, otherwise return 0 if (!s->count_selected_rows()) { - return 0; + return -1; } - const auto iter = s->get_selected(); - const Gtk::TreeModel::Row row = *iter; - int id = row[spots_.id]; + const auto selRow = s->get_selected(); - return id; + // Get selected spot index + int index = -1; + + for (auto i : treemodel_->children()) { + index++; + + if (selRow == i) { + return index; + } + } + + return -1; } -bool ControlSpotPanel::setSelectedSpot(const int id) +bool ControlSpotPanel::setSelectedSpot(const int index) { - // printf("setSelectedSpot: %d\n", id); + // printf("setSelectedSpot: %d\n", index); MyMutex::MyLock lock(mTreeview); - const Gtk::TreeModel::Children children = treemodel_->children(); + int i = -1; - for (auto iter = children.begin(); iter != children.end(); iter++) { - const Gtk::TreeModel::Row row = *iter; + for (auto &row : treemodel_->children()) { + i++; - if (row[spots_.id] == id) { + if (i == index) { disableParamlistener(true); treeview_->set_cursor(treemodel_->get_path(row)); @@ -1842,36 +1811,15 @@ bool ControlSpotPanel::setSelectedSpot(const int id) return false; } -int ControlSpotPanel::getNewId() -{ - MyMutex::MyLock lock(mTreeview); - - // Looking for maximum used id - int max_row_id = 0; - const Gtk::TreeModel::Children children = treemodel_->children(); - - for (auto iter = children.begin(); iter != children.end(); iter++) { - const Gtk::TreeModel::Row row = *iter; - const int iter_id = row[spots_.id]; - max_row_id = std::max(max_row_id, iter_id); - } - - max_row_id++; - - return max_row_id; -} - - void ControlSpotPanel::addControlSpot(SpotRow* newSpot) { - // printf("addControlSpot: %d\n", newSpot->id); + // printf("addControlSpot: %d\n", newSpot->name); MyMutex::MyLock lock(mTreeview); disableParamlistener(true); - Gtk::TreeModel::Row row = * (treemodel_->append()); + Gtk::TreeModel::Row row = *(treemodel_->append()); row[spots_.mouseover] = false; - row[spots_.id] = newSpot->id; row[spots_.name] = newSpot->name; row[spots_.isvisible] = newSpot->isvisible; row[spots_.curveid] = 0; // No associated curve @@ -1904,57 +1852,7 @@ void ControlSpotPanel::addControlSpot(SpotRow* newSpot) updateControlSpotCurve(row); } -int ControlSpotPanel::updateControlSpot(SpotRow* spot) -{ - // printf("updateControlSpot: %d\n", spot->id); - - MyMutex::MyLock lock(mTreeview); - - disableParamlistener(true); - - const Gtk::TreeModel::Children children = treemodel_->children(); - - for (auto iter = children.begin(); iter != children.end(); iter++) { - Gtk::TreeModel::Row row = *iter; - - if (row[spots_.id] == spot->id) { - row[spots_.name] = spot->name; - row[spots_.isvisible] = spot->isvisible; - row[spots_.shape] = spot->shape; - row[spots_.spotMethod] = spot->spotMethod; - row[spots_.sensiexclu] = spot->sensiexclu; - row[spots_.structexclu] = spot->structexclu; - row[spots_.struc] = spot->struc; - row[spots_.shapeMethod] = spot->shapeMethod; - row[spots_.locX] = spot->locX; - row[spots_.locXL] = spot->locXL; - row[spots_.locY] = spot->locY; - row[spots_.locYT] = spot->locYT; - row[spots_.centerX] = spot->centerX; - row[spots_.centerY] = spot->centerY; - row[spots_.circrad] = spot->circrad; - row[spots_.qualityMethod] = spot->qualityMethod; - row[spots_.transit] = spot->transit; - row[spots_.thresh] = spot->thresh; - row[spots_.iter] = spot->iter; - row[spots_.balan] = spot->balan; - row[spots_.transitweak] = spot->transitweak; - row[spots_.transitgrad] = spot->transitgrad; - row[spots_.avoid] = spot->avoid; - - updateControlSpotCurve(row); - updateParamVisibility(); - disableParamlistener(false); - - return 1; - } - } - - disableParamlistener(false); - return 0; -} - -void ControlSpotPanel::deleteControlSpot(const int id) +void ControlSpotPanel::deleteControlSpot(const int index) { // printf("deleteControlSpot: %d\n", id); @@ -1962,14 +1860,15 @@ void ControlSpotPanel::deleteControlSpot(const int id) disableParamlistener(true); - const Gtk::TreeModel::Children children = treemodel_->children(); + int i = -1; - for (auto iter = children.begin(); iter != children.end(); iter++) { - Gtk::TreeModel::Row row = *iter; + for (auto iter : treemodel_->children()) { + i++; - if (row[spots_.id] == id) { + if (i == index) { + Gtk::TreeModel::Row row = *iter; deleteControlSpotCurve(row); - treemodel_->erase(iter); + treemodel_->erase(*row); break; } } @@ -1977,138 +1876,6 @@ void ControlSpotPanel::deleteControlSpot(const int id) disableParamlistener(false); } -ControlSpotPanel::SpotEdited* ControlSpotPanel::getEditedStates() -{ - // printf("getEditedStates\n"); - - SpotEdited* se = new SpotEdited(); - - if (nbSpotChanged_) { - se->nbspot = true; - // nbSpotChanged_ = false; - } else { - se->nbspot = false; - } - - if (selSpotChanged_) { - se->selspot = true; - // selSpotChanged_ = false; - } else { - se->selspot = false; - } - - if (nameChanged_) { - se->name = true; - // nameChanged_ = false; - } else { - se->name = false; - } - - if (visibilityChanged_) { - se->isvisible = true; - // visibilityChanged_ = false; - } else { - se->isvisible = false; - } - - se->shape = shape_->get_active_text() != M("GENERAL_UNCHANGED"); - se->spotMethod = spotMethod_->get_active_text() != M("GENERAL_UNCHANGED"); - se->sensiexclu = sensiexclu_->getEditedState(); - se->structexclu = structexclu_->getEditedState(); - se->struc = struc_->getEditedState(); - se->shapeMethod = shapeMethod_->get_active_text() != M("GENERAL_UNCHANGED"); - se->locX = locX_->getEditedState(); - se->locXL = locXL_->getEditedState(); - se->locY = locY_->getEditedState(); - se->locYT = locYT_->getEditedState(); - se->centerX = centerX_->getEditedState(); - se-> centerY = centerY_->getEditedState(); - se->circrad = circrad_->getEditedState(); - se->qualityMethod = qualityMethod_->get_active_text() != M("GENERAL_UNCHANGED"); - se->transit = transit_->getEditedState(); - se->thresh = thresh_->getEditedState(); - se->iter = iter_->getEditedState(); - se->balan = balan_->getEditedState(); - se->transitweak = transitweak_->getEditedState(); - se->transitgrad = transitgrad_->getEditedState(); - se->avoid = !avoid_->get_inconsistent(); - - return se; -} - -void ControlSpotPanel::setEditedStates(SpotEdited* se) -{ - // printf("setEditedStates\n"); - - // Reset treeview edited states - nbSpotChanged_ = false; - selSpotChanged_ = false; - nameChanged_ = false; - visibilityChanged_ = false; - - // Disable params listeners - disableParamlistener(true); - - // Set widgets edited states - if (!se->nbspot || !se->selspot) { - treeview_->set_sensitive(false); - button_add_->set_sensitive(false); - button_delete_->set_sensitive(false); - button_duplicate_->set_sensitive(false); - button_rename_->set_sensitive(false); - button_visibility_->set_sensitive(false); - } else { - treeview_->set_sensitive(true); - button_add_->set_sensitive(true); - button_delete_->set_sensitive(true); - button_duplicate_->set_sensitive(true); - button_rename_->set_sensitive(se->name); - button_visibility_->set_sensitive(se->isvisible); - } - - if (!se->shape) { - shape_->set_active_text(M("GENERAL_UNCHANGED")); - } - - if (!se->spotMethod) { - spotMethod_->set_active_text(M("GENERAL_UNCHANGED")); - } - - sensiexclu_->setEditedState(se->sensiexclu ? Edited : UnEdited); - structexclu_->setEditedState(se->structexclu ? Edited : UnEdited); - struc_->setEditedState(se->struc ? Edited : UnEdited); - - if (!se->shapeMethod) { - shapeMethod_->set_active_text(M("GENERAL_UNCHANGED")); - } - - locX_->setEditedState(se->locX ? Edited : UnEdited); - locXL_->setEditedState(se->locXL ? Edited : UnEdited); - locY_->setEditedState(se->locY ? Edited : UnEdited); - locYT_->setEditedState(se->locYT ? Edited : UnEdited); - centerX_->setEditedState(se->centerX ? Edited : UnEdited); - centerY_->setEditedState(se->centerY ? Edited : UnEdited); - circrad_->setEditedState(se->circrad ? Edited : UnEdited); - - if (!se->qualityMethod) { - qualityMethod_->set_active_text(M("GENERAL_UNCHANGED")); - } - - transit_->setEditedState(se->transit ? Edited : UnEdited); - thresh_->setEditedState(se->thresh ? Edited : UnEdited); - iter_->setEditedState(se->iter ? Edited : UnEdited); - balan_->setEditedState(se->balan ? Edited : UnEdited); - transitweak_->setEditedState(se->transitweak ? Edited : UnEdited); - transitgrad_->setEditedState(se->transitgrad ? Edited : UnEdited); - avoid_->set_inconsistent(multiImage && !se->avoid); - - // Update Control Spot GUI according to widgets edited states - updateParamVisibility(); - - // Enable params listeners - disableParamlistener(false); -} - void ControlSpotPanel::setDefaults(const rtengine::procparams::ProcParams * defParams, const ParamsEdited * pedited) { const int index = defParams->locallab.selspot; @@ -2138,35 +1905,6 @@ void ControlSpotPanel::setDefaults(const rtengine::procparams::ProcParams * defP // Note: No need to manage pedited as batch mode is deactivated for Locallab } -void ControlSpotPanel::setBatchMode(bool batchMode) -{ - ToolPanel::setBatchMode(batchMode); - - // Set batch mode for adjusters - sensiexclu_->showEditedCB(); - structexclu_->showEditedCB(); - struc_->showEditedCB(); - locX_->showEditedCB(); - locXL_->showEditedCB(); - locY_->showEditedCB(); - locYT_->showEditedCB(); - centerX_->showEditedCB(); - centerY_->showEditedCB(); - circrad_->showEditedCB(); - transit_->showEditedCB(); - thresh_->showEditedCB(); - iter_->showEditedCB(); - balan_->showEditedCB(); - transitweak_->showEditedCB(); - transitgrad_->showEditedCB(); - - // Set batch mode for comboBoxText - shape_->append(M("GENERAL_UNCHANGED")); - spotMethod_->append(M("GENERAL_UNCHANGED")); - shapeMethod_->append(M("GENERAL_UNCHANGED")); - qualityMethod_->append(M("GENERAL_UNCHANGED")); -} - //----------------------------------------------------------------------------- // ControlSpots //----------------------------------------------------------------------------- @@ -2174,7 +1912,6 @@ void ControlSpotPanel::setBatchMode(bool batchMode) ControlSpotPanel::ControlSpots::ControlSpots() { add(mouseover); - add(id); add(name); add(isvisible); add(curveid); diff --git a/rtgui/controlspotpanel.h b/rtgui/controlspotpanel.h index d64c9e940..07d9c7454 100644 --- a/rtgui/controlspotpanel.h +++ b/rtgui/controlspotpanel.h @@ -41,7 +41,6 @@ public: * A SpotRow structure allows exchanges from and to ControlSpotClass */ struct SpotRow { - int id; // Control spot id Glib::ustring name; bool isvisible; int shape; // 0 = Ellipse, 1 = Rectangle @@ -67,37 +66,6 @@ public: bool avoid; }; - /** - * A SpotEdited structure allows exchanges of spot panel widgets edited states from and to ControlSpotClass - */ - struct SpotEdited { - bool nbspot; - bool selspot; - bool name; - bool isvisible; - bool shape; - bool spotMethod; - bool sensiexclu; - bool structexclu; - bool struc; - bool shapeMethod; - bool locX; - bool locXL; - bool locY; - bool locYT; - bool centerX; - bool centerY; - bool circrad; - bool qualityMethod; - bool transit; - bool thresh; - bool iter; - bool balan; - bool transitweak; - bool transitgrad; - bool avoid; - }; - /** * An event type enumeration allows exchanges of spot panel event type from and to ControlSpotClass */ @@ -134,29 +102,29 @@ public: /** * Getter of params of associated spot * - * @param id The spot id to get params + * @param index The spot index to get params * @return A SpotRow structure containing params of associated spot */ - SpotRow* getSpot(const int id); + SpotRow* getSpot(const int index); /** - * Get of spot id list + * Getter of spots number * - * @return A vector contening the list of spot id + * @return The number of spots in panel */ - std::vector* getSpotIdList(); + int getSpotNumber(); /** - * Getter of selected spot id + * Getter of selected spot index * - * @return The id of selected spot in treeview (return 0 if no selected spot) + * @return The index of selected spot in treeview (return -1 if no selected spot) */ int getSelectedSpot(); /** * Setter of selected spot * - * @param id The id of spot to be selected - * @return True if a spot corresponding to the id has been selected + * @param index The index of spot to be selected + * @return True if a spot corresponding to the index has been selected */ - bool setSelectedSpot(const int id); + bool setSelectedSpot(const int index); /** * Setter for mask preview active indicator * @@ -168,12 +136,6 @@ public: } // Control spot creation functions - /** - * Getter of available id for new spot creation - * - * @return An available id (i.e. max existing ones + 1) - */ - int getNewId(); /** * Add a new spot (and its associated curve) * @@ -181,35 +143,15 @@ public: */ void addControlSpot(SpotRow* newSpot); - // Control spot update function - /** - * Update a spot (and its associated curve) - * - * @param spot A SpotRow structure containing spot params to update - */ - int updateControlSpot(SpotRow* spot); - // Control spot delete function /** * Delete a spot (and its associated curve) * * @param id The id of the spot to be deleted */ - void deleteControlSpot(const int id); + void deleteControlSpot(const int index); // Panel widgets management functions - /** - * Getter of panel widgets edited states - * - * @return A SpotEdited structure containing the widgets edited states - */ - SpotEdited* getEditedStates(); - /** - * Setter of panel widgets edited states - * - * @param se A SpotEdited structure containing the widgets edited states to update - */ - void setEditedStates(SpotEdited* se); /** * Implementation of setDefaults function of toolpanel.h * @@ -225,16 +167,10 @@ public: void setParamEditable(bool cond); // Batch mode management - /** - * Implementation of setBatchMode function of toolpanel.h - * - * @param batchMode Condition to enable batch mode - */ - void setBatchMode(bool batchMode); + // Note: Batch mode is deactivated for Locallab private: // Cell renderer - void render_id(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); void render_name(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); void render_isvisible(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); @@ -279,7 +215,6 @@ private: ControlSpots(); Gtk::TreeModelColumn mouseover; // Used to manage spot enlightening when mouse over - Gtk::TreeModelColumn id; // Control spot id Gtk::TreeModelColumn name; Gtk::TreeModelColumn isvisible; Gtk::TreeModelColumn curveid; // Associated curve id diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 2b5e25e5c..59831bf67 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1752,7 +1752,7 @@ void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) PartialProfile pp (true); pp.set (true); * (pp.pparams) = openThm->getProcParams(); - pp.pedited->locallab.spots.resize(pp.pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + pp.pedited->locallab.spots.resize(pp.pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); tpc->profileChange (&pp, rtengine::EvProfileChangeNotification, M ("PROGRESSDLG_PROFILECHANGEDINBROWSER")); pp.deleteInstance(); } diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 9a133fda2..513d131a7 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -1070,6 +1070,8 @@ void FileBrowser::partPasteProfile () auto toplevel = static_cast (get_toplevel ()); PartialPasteDlg partialPasteDlg (M("PARTIALPASTE_DIALOGLABEL"), toplevel); + partialPasteDlg.updateSpotWidget(clipboard.getPartialProfile().pparams); + int i = partialPasteDlg.run (); if (i == Gtk::RESPONSE_OK) { @@ -1396,6 +1398,8 @@ void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label) auto toplevel = static_cast (get_toplevel ()); PartialPasteDlg partialPasteDlg (M("PARTIALPASTE_DIALOGLABEL"), toplevel); + partialPasteDlg.updateSpotWidget(srcProfiles->pparams); + if (partialPasteDlg.run() == Gtk::RESPONSE_OK) { MYREADERLOCK(l, entryRW); @@ -1410,7 +1414,7 @@ void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label) rtengine::procparams::PartialProfile dstProfile(true); *dstProfile.pparams = (static_cast(selected[i]))->thumbnail->getProcParams (); dstProfile.set(true); - dstProfile.pedited->locallab.spots.resize(dstProfile.pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + dstProfile.pedited->locallab.spots.resize(dstProfile.pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); partialPasteDlg.applyPaste (dstProfile.pparams, dstProfile.pedited, srcProfiles->pparams, srcProfiles->pedited); (static_cast(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER); dstProfile.deleteInstance(); diff --git a/rtgui/history.cc b/rtgui/history.cc index f928f95e5..5051c1158 100644 --- a/rtgui/history.cc +++ b/rtgui/history.cc @@ -179,7 +179,7 @@ void History::historySelectionChanged () if (row && tpc) { ProcParams pparams = row[historyColumns.params]; ParamsEdited pe (true); - pe.locallab.spots.resize(pparams.locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + pe.locallab.spots.resize(pparams.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); PartialProfile pp (&pparams, &pe); ParamsEdited paramsEdited = row[historyColumns.paramsEdited]; @@ -214,7 +214,7 @@ void History::bookmarkSelectionChanged () if (row && tpc) { ProcParams pparams = row[bookmarkColumns.params]; ParamsEdited pe (true); - pe.locallab.spots.resize(pparams.locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + pe.locallab.spots.resize(pparams.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); PartialProfile pp (&pparams, &pe); ParamsEdited paramsEdited = row[bookmarkColumns.paramsEdited]; tpc->profileChange (&pp, EvBookmarkSelected, row[bookmarkColumns.text], ¶msEdited); diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 95f515891..3417bccc2 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -226,18 +226,17 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit // TODO Manage it with read function in controlspotpanel.cc // Delete all existent spots - std::vector* const list = expsettings->getSpotIdList(); + const int spotNb = expsettings->getSpotNumber(); - for (size_t i = 0; i < list->size(); i++) { - expsettings->deleteControlSpot(list->at(i)); + for (int i = spotNb - 1; i >= 0; i--) { + expsettings->deleteControlSpot(i); } // TODO Manage it with read function in controlspotpanel.cc // Add existent spots based on pp ControlSpotPanel::SpotRow* const r = new ControlSpotPanel::SpotRow(); - for (int i = 0; i < pp->locallab.nbspot && i < (int)pp->locallab.spots.size(); i++) { - r->id = pp->locallab.spots.at(i).id; + for (int i = 0; i < (int)pp->locallab.spots.size(); i++) { r->name = pp->locallab.spots.at(i).name; r->isvisible = pp->locallab.spots.at(i).isvisible; @@ -293,8 +292,8 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit } // Select active spot - if (pp->locallab.nbspot > 0) { - expsettings->setSelectedSpot(pp->locallab.spots.at(pp->locallab.selspot).id); + if (pp->locallab.spots.size() > 0) { + expsettings->setSelectedSpot(pp->locallab.selspot); } // Update each Locallab tools GUI @@ -315,7 +314,7 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit } // Specific case: if there is no spot, GUI isn't anymore editable (i.e. Locallab tool cannot be managed) - if (pp->locallab.nbspot > 0) { + if (pp->locallab.spots.size() > 0) { setParamEditable(true); } else { setParamEditable(false); @@ -341,7 +340,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } const int spotPanelEvent = expsettings->getEventType(); - int spotId; + int spotIndex; ControlSpotPanel::SpotRow* r; LocallabParams::LocallabSpot* newSpot; @@ -356,10 +355,8 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited case (ControlSpotPanel::SpotCreation): // Spot creation event // Spot creation (default initialization) newSpot = new LocallabParams::LocallabSpot(); - spotId = expsettings->getNewId(); r = new ControlSpotPanel::SpotRow(); - r->id = newSpot->id = spotId; - r->name = newSpot->name = M("TP_LOCALLAB_SPOTNAME") + std::to_string(spotId); + r->name = newSpot->name = M("TP_LOCALLAB_SPOTNAME"); r->isvisible = newSpot->isvisible; if (newSpot->shape == "ELI") { @@ -431,12 +428,11 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited expsettings->addControlSpot(r); // ProcParams update - pp->locallab.nbspot++; - pp->locallab.selspot = pp->locallab.nbspot - 1; pp->locallab.spots.push_back(*newSpot); + pp->locallab.selspot = pp->locallab.spots.size() - 1; // New created spot selection - expsettings->setSelectedSpot(spotId); + expsettings->setSelectedSpot(pp->locallab.selspot); // Update Locallab tools GUI with new created spot disableListener(); @@ -459,7 +455,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } } - if (pp->locallab.nbspot == 1) { + if (pp->locallab.spots.size() == 1) { setParamEditable(true); } @@ -475,17 +471,16 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited case (ControlSpotPanel::SpotDeletion): // Spot deletion event // Get deleted spot index in ProcParams and update it - spotId = expsettings->getSelectedSpot(); + spotIndex = expsettings->getSelectedSpot(); - for (int i = 0; i < pp->locallab.nbspot && i < (int)pp->locallab.spots.size(); i++) { - if (pp->locallab.spots.at(i).id == spotId) { + for (int i = 0; i < (int)pp->locallab.spots.size(); i++) { + if (i == spotIndex) { // ProcParams update - pp->locallab.nbspot--; pp->locallab.spots.erase(pp->locallab.spots.begin() + i); - expsettings->deleteControlSpot(spotId); + expsettings->deleteControlSpot(spotIndex); // Select the first remaining spot before deleted one - if (pp->locallab.nbspot > 0) { + if (pp->locallab.spots.size() > 0) { for (int j = i - 1; j >= 0; j--) { // procparams spots uses zero-based index whereas spot ids use one-based index if (expsettings->setSelectedSpot(j + 1)) { // True if an existing spot has been selected on controlspotpanel pp->locallab.selspot = j; @@ -519,7 +514,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } } - if (pp->locallab.nbspot == 0) { + if (pp->locallab.spots.size() == 0) { setParamEditable(false); } @@ -538,17 +533,10 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited break; case (ControlSpotPanel::SpotSelection): // Spot selection event - spotId = expsettings->getSelectedSpot(); - - for (int i = 0; i < pp->locallab.nbspot && i < (int)pp->locallab.spots.size(); i++) { - if (pp->locallab.spots.at(i).id == spotId) { - pp->locallab.selspot = i; - break; - } - } + pp->locallab.selspot = expsettings->getSelectedSpot(); // Update control spots and Locallab tools GUI with selected spot - expsettings->setSelectedSpot(spotId); + expsettings->setSelectedSpot(pp->locallab.selspot); disableListener(); for (auto tool : locallabTools) { @@ -592,10 +580,10 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited case (ControlSpotPanel::SpotDuplication): // Spot duplication event newSpot = nullptr; - spotId = expsettings->getSelectedSpot(); + spotIndex = expsettings->getSelectedSpot(); - for (int i = 0; i < pp->locallab.nbspot && i < (int)pp->locallab.spots.size(); i++) { - if (pp->locallab.spots.at(i).id == spotId) { + for (int i = 0; i < (int)pp->locallab.spots.size(); i++) { + if (i == spotIndex) { newSpot = new LocallabParams::LocallabSpot(pp->locallab.spots.at(i)); break; } @@ -606,9 +594,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } // Spot creation (initialization at currently selected spot) - spotId = expsettings->getNewId(); r = new ControlSpotPanel::SpotRow(); - r->id = newSpot->id = spotId; r->name = newSpot->name = newSpot->name + " - " + M("TP_LOCALLAB_DUPLSPOTNAME"); r->isvisible = newSpot->isvisible; @@ -681,12 +667,12 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited expsettings->addControlSpot(r); // ProcParams update - pp->locallab.nbspot++; - pp->locallab.selspot = pp->locallab.nbspot - 1; pp->locallab.spots.push_back(*newSpot); + pp->locallab.selspot = pp->locallab.spots.size() - 1; + // New created spot selection - expsettings->setSelectedSpot(spotId); + expsettings->setSelectedSpot(pp->locallab.selspot); // Update Locallab tools GUI with new created spot disableListener(); @@ -732,7 +718,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited break; default: // Spot or locallab GUI updated - if (pp->locallab.nbspot > 0) { + if (pp->locallab.spots.size() > 0) { r = expsettings->getSpot(expsettings->getSelectedSpot()); // ProcParams update diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 7d7f3a5a8..6d1ea4571 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -335,9 +335,7 @@ void ParamsEdited::set(bool v) gradient.centerY = v; locallab.enabled = v; - locallab.nbspot = v; locallab.selspot = v; - locallab.id = v; for (size_t i = 0; i < locallab.spots.size(); i++) { locallab.spots.at(i).set(v); @@ -615,7 +613,10 @@ void ParamsEdited::initFrom(const std::vector& // Resize LocallabSpotEdited according to src[0] locallab.spots.clear(); - locallab.spots.resize(p.locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + locallab.spots.resize(p.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); + + // Variable used to determined if Locallab spots number is equal and so spots can be combined + bool isSpotNumberEqual = true; for (size_t i = 1; i < src.size(); i++) { const ProcParams& other = src[i]; @@ -922,15 +923,14 @@ void ParamsEdited::initFrom(const std::vector& gradient.centerY = gradient.centerY && p.gradient.centerY == other.gradient.centerY; locallab.enabled = locallab.enabled && p.locallab.enabled == other.locallab.enabled; - locallab.nbspot = locallab.nbspot && p.locallab.nbspot == other.locallab.nbspot; + isSpotNumberEqual = isSpotNumberEqual && p.locallab.spots.size() == other.locallab.spots.size(); locallab.selspot = locallab.selspot && p.locallab.selspot == other.locallab.selspot; - if (locallab.nbspot) { + if (isSpotNumberEqual) { for (size_t j = 0; j < locallab.spots.size() && j < p.locallab.spots.size() && j < other.locallab.spots.size(); j++) { const LocallabParams::LocallabSpot& pSpot = p.locallab.spots.at(j); const LocallabParams::LocallabSpot& otherSpot = other.locallab.spots.at(j); // Control spot settings - locallab.id = locallab.id && pSpot.id == otherSpot.id; locallab.spots.at(j).name = locallab.spots.at(j).name && pSpot.name == otherSpot.name; locallab.spots.at(j).isvisible = locallab.spots.at(j).isvisible && pSpot.isvisible == otherSpot.isvisible; locallab.spots.at(j).shape = locallab.spots.at(j).shape && pSpot.shape == otherSpot.shape; @@ -1179,11 +1179,10 @@ void ParamsEdited::initFrom(const std::vector& } } - if (!locallab.nbspot || !locallab.id) { - // locallab.id and locallab.spots are set to false because cannot be combined - locallab.id = false; + if (!isSpotNumberEqual) { + // All LocallabSpotEdited are set to false because cannot be combined locallab.spots.clear(); - locallab.spots.resize(p.locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(false)); + locallab.spots.resize(p.locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(false)); } pcvignette.enabled = pcvignette.enabled && p.pcvignette.enabled == other.pcvignette.enabled; @@ -2573,36 +2572,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.enabled = mods.locallab.enabled; } - if (locallab.nbspot || locallab.id) { // For locallab to work, id order needs to be maintained when adding or deleting spots - // Saving toEdit locallab temporarily - LocallabParams tmpLocallab = toEdit.locallab; - - // Removing all spots in toEdit and recreating spots based on mods id - toEdit.locallab.spots.clear(); - - for (size_t i = 0; i < mods.locallab.spots.size(); i++) { - LocallabParams::LocallabSpot *newSpot = new LocallabParams::LocallabSpot(); - newSpot->id = mods.locallab.spots.at(i).id; - toEdit.locallab.spots.push_back(*newSpot); - } - - // Common spots in tmpLocallab and mods are restored in toEdit - for (size_t i = 0; i < toEdit.locallab.spots.size(); i++) { - for (size_t j = 0; j < tmpLocallab.spots.size(); j++) { - if (toEdit.locallab.spots.at(i).id == tmpLocallab.spots.at(j).id) { - toEdit.locallab.spots.at(i) = tmpLocallab.spots.at(j); - } - } - } - - // Updating nbspot accordingly - toEdit.locallab.nbspot = mods.locallab.nbspot; - } - if (locallab.selspot) { toEdit.locallab.selspot = mods.locallab.selspot; } + // Resizing locallab spots vector according to pedited + toEdit.locallab.spots.resize(locallab.spots.size()); + + // Updating each locallab spot according to pedited for (size_t i = 0; i < toEdit.locallab.spots.size() && i < mods.locallab.spots.size() && i < locallab.spots.size(); i++) { // Control spot settings if (locallab.spots.at(i).name) { @@ -3533,7 +3510,6 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } } - if (pcvignette.enabled) { toEdit.pcvignette.enabled = mods.pcvignette.enabled; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 4a9d1fbf0..0ec8efce6 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -602,9 +602,7 @@ public: }; bool enabled; - bool nbspot; bool selspot; - bool id; std::vector spots; }; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 89c5047d4..d692d121a 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -24,6 +24,167 @@ #include "../rtengine/procparams.h" +using namespace rtengine::procparams; + +/* ==== PartialSpotWidget ==== */ +PartialSpotWidget::PartialSpotWidget(): + // Widget GUI elements + treeview(Gtk::manage(new Gtk::TreeView())), + treemodel(Gtk::ListStore::create(spotRow)), + + // Widget listener + selListener(nullptr) +{ + // Configure tree view + treeview->set_model(treemodel); + treeview->set_enable_search(false); + treeview->set_headers_visible(false); + + // Add tree view columns + auto cell1 = Gtk::manage(new Gtk::CellRendererToggle()); + cell1->signal_toggled().connect( + sigc::mem_fun( + *this, &PartialSpotWidget::keepToggled)); + int cols_count = treeview->append_column("", *cell1); + auto col = treeview->get_column(cols_count - 1); + + if (col) { + col->set_cell_data_func( + *cell1, sigc::mem_fun( + *this, &PartialSpotWidget::render_keep)); + } + + auto cell2 = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview->append_column("", *cell2); + col = treeview->get_column(cols_count - 1); + + if (col) { + col->set_cell_data_func( + *cell2, sigc::mem_fun( + *this, &PartialSpotWidget::render_spotname)); + } + + // Create and configure scrolled window + Gtk::ScrolledWindow* const scrolledwindows = Gtk::manage(new Gtk::ScrolledWindow()); + scrolledwindows->add(*treeview); + scrolledwindows->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + scrolledwindows->set_min_content_height(100); + + // Add widgets to VBox + pack_start(*scrolledwindows); + show_all(); +} + +void PartialSpotWidget::updateSpotWidget(const rtengine::procparams::ProcParams* pp, const bool defValue) +{ + treeviewconn.block(true); + + // Clear tree model + treemodel->clear(); + + // Add tree model element according to pp + Gtk::TreeRow newspot; + + for (size_t i = 0; i < pp->locallab.spots.size(); i++) { + newspot = *(treemodel->append()); + newspot[spotRow.keep] = defValue; + newspot[spotRow.spotname] = pp->locallab.spots.at(i).name; + } + + treeviewconn.block(false); +} + +void PartialSpotWidget::enableAll() +{ + treeviewconn.block(true); + + for (auto &spot : treemodel->children()) { + spot[spotRow.keep] = true; + } + + treeviewconn.block(false); +} + +void PartialSpotWidget::disableAll() +{ + treeviewconn.block(true); + + for (auto &spot : treemodel->children()) { + spot[spotRow.keep] = false; + } + + treeviewconn.block(false); +} + +std::vector PartialSpotWidget::getSelectionStatus() +{ + std::vector keepVect; + + for (auto &spot : treemodel->children()) { + keepVect.push_back(spot[spotRow.keep]); + } + + return keepVect; +} + +void PartialSpotWidget::render_keep(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter) +{ + const auto spot = *iter; + Gtk::CellRendererToggle* const ct = static_cast(cell); + + // Render cell toggle + ct->property_active() = spot[spotRow.keep]; +} + +void PartialSpotWidget::render_spotname(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter) +{ + const auto spot = *iter; + Gtk::CellRendererText* const ct = static_cast(cell); + + // Render cell toggle + ct->property_text() = spot[spotRow.spotname]; +} + +void PartialSpotWidget::keepToggled(const Glib::ustring &path) +{ + PartialSpotWidgetListener::UpdateStatus status; + + // Get clicked row + const auto selRow = *(treemodel->get_iter(path)); + + // Update treeview according to selected row + selRow[spotRow.keep] = !selRow[spotRow.keep]; + + // Count total number of spot + const int totalnb = (int)treemodel->children().size(); + + // Count number of toggled elements + int togglednb = 0; + + for (auto &spot : treemodel->children()) { + if (spot[spotRow.keep]) { + togglednb++; + } + } + + // Compute status + if (togglednb == 0) { // No spot toggled + status = PartialSpotWidgetListener::UpdateStatus::NoSelection; + } else { + if (togglednb == totalnb) { // All spot toggled + status = PartialSpotWidgetListener::UpdateStatus::AllSelection; + } else { // Partial number of spots toggled + status = PartialSpotWidgetListener::UpdateStatus::PartialSelection; + } + } + + // Propagate event to listener + if (selListener) { + selListener->partialSpotUpdated(status); + } +} + +/* ==== PartialPasteDlg ==== */ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent) : Gtk::Dialog (title, *parent, true) { @@ -108,6 +269,10 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren exifch = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EXIFCHANGES"))); iptc = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_IPTCINFO"))); + // Locallab: + spots = Gtk::manage(new PartialSpotWidget()); + spots->setPartialSpotWidgetListener(this); + // Raw Settings: raw_method = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DMETHOD"))); raw_imagenum = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_IMAGENUM"))); @@ -218,6 +383,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren //LOCALLAB vboxes[6]->pack_start(*locallab, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start(*spots, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*hseps[6], Gtk::PACK_SHRINK, 2); //META @@ -663,6 +829,12 @@ void PartialPasteDlg::metaToggled () void PartialPasteDlg::locallabToggled() { locallab->set_inconsistent (false); + + if (locallab->get_active()) { + spots->enableAll(); + } else { + spots->disableAll(); + } } @@ -674,9 +846,9 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param { ParamsEdited falsePE; // falsePE is a workaround to set a group of ParamsEdited to false - falsePE.locallab.spots.resize(srcPP->locallab.nbspot, LocallabParamsEdited::LocallabSpotEdited(false)); + falsePE.locallab.spots.resize(srcPP->locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(false)); ParamsEdited filterPE(true); // Contains the initial information about the loaded values - filterPE.locallab.spots.resize(srcPP->locallab.nbspot, LocallabParamsEdited::LocallabSpotEdited(true)); + filterPE.locallab.spots.resize(srcPP->locallab.spots.size(), LocallabParamsEdited::LocallabSpotEdited(true)); if (srcPE) { filterPE = *srcPE; @@ -994,10 +1166,6 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.ff_AutoClipControl = falsePE.raw.ff_AutoClipControl; } - if (!locallab->get_active ()) { - filterPE.locallab = falsePE.locallab; - } - if (!filmNegative->get_active ()) { filterPE.filmNegative.enabled = falsePE.filmNegative.enabled; filterPE.filmNegative.redRatio = falsePE.filmNegative.redRatio; @@ -1005,11 +1173,67 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.filmNegative.blueRatio = falsePE.filmNegative.blueRatio; } - if (dstPE) { - *dstPE = filterPE; - } + // Locallab shall be kept in last position + if (!locallab->get_active () && !locallab->get_inconsistent()) { + filterPE.locallab = falsePE.locallab; - // Apply the filter! - filterPE.combine(*dstPP, *srcPP, true); + if (dstPE) { + *dstPE = filterPE; + } + + // Apply the filter! + filterPE.combine(*dstPP, *srcPP, true); + } else { // Update PE and PP according to chosen spot + // Get chosen spots + std::vector chosenSpots = spots->getSelectionStatus(); + + // Create temporary PP and PE based on scrPP and scrPE + rtengine::procparams::ProcParams tmpPP = rtengine::procparams::ProcParams(*srcPP); + ParamsEdited tmpPE = ParamsEdited(filterPE); + + // Update tmpPP and tmpPE according to chosen spots + for (int i = ((int)chosenSpots.size() - 1); i >= 0; i--) { + if (!chosenSpots.at(i)) { + tmpPP.locallab.spots.erase(tmpPP.locallab.spots.begin() + i); + tmpPE.locallab.spots.erase(tmpPE.locallab.spots.begin() + i); + } + } + + if (dstPE) { + *dstPE = tmpPE; + } + + // Apply the filter! + tmpPE.combine(*dstPP, tmpPP, true); + } +} + +void PartialPasteDlg::updateSpotWidget(const rtengine::procparams::ProcParams* pp) +{ + locallab->set_inconsistent(false); + + if (pp->locallab.spots.size() > 0) { + spots->set_visible(true); + spots->updateSpotWidget(pp, locallab->get_active()); + } else { + spots->set_visible(false); // Hide widget if there is no locallab spot + } + +} + +void PartialPasteDlg::partialSpotUpdated(const UpdateStatus status) +{ + switch (status) { + case (AllSelection): + locallab->set_active(true); + break; + + case (NoSelection): + locallab->set_active(false); + break; + + case (PartialSelection): + locallab->set_inconsistent(true); + } } diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 9927bace6..dc7f64c53 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -24,7 +24,81 @@ struct ParamsEdited; -class PartialPasteDlg : public Gtk::Dialog +/* ==== PartialSpotWidgetListener ==== */ +class PartialSpotWidget; +class PartialSpotWidgetListener +{ +public: + enum UpdateStatus { + AllSelection = 1, + NoSelection = 2, + PartialSelection = 3 + }; + +public: + PartialSpotWidgetListener() {}; + virtual ~PartialSpotWidgetListener() {}; + + virtual void partialSpotUpdated(const UpdateStatus status) = 0; +}; + +/* ==== PartialSpotWidget ==== */ +class PartialSpotWidget: + public Gtk::VBox +{ +private: + // Tree model to manage spot selection widget + class SpotRow: + public Gtk::TreeModel::ColumnRecord + { + public: + Gtk::TreeModelColumn keep; + Gtk::TreeModelColumn spotname; + + SpotRow() + { + add(keep); + add(spotname); + } + }; + + // Spot selection widgets + Gtk::TreeView* const treeview; + sigc::connection treeviewconn; + SpotRow spotRow; + Glib::RefPtr treemodel; + + // Spot selection listener + PartialSpotWidgetListener* selListener; + +public: + PartialSpotWidget(); + + // Setter for spot selection listener + void setPartialSpotWidgetListener(PartialSpotWidgetListener* pswl) + { + selListener = pswl; + } + + // Spot selection widget management functions + void updateSpotWidget(const rtengine::procparams::ProcParams* pp, const bool defValue); + void enableAll(); + void disableAll(); + std::vector getSelectionStatus(); + +private: + // GUI aspect management functions + void render_keep(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + void render_spotname(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter); + + // Event management function + void keepToggled(const Glib::ustring &path); +}; + +/* ==== PartialPasteDlg ==== */ +class PartialPasteDlg: + public Gtk::Dialog, + public PartialSpotWidgetListener { public: @@ -102,6 +176,8 @@ public: Gtk::CheckButton* exifch; Gtk::CheckButton* iptc; + // options in locallab: + PartialSpotWidget* spots; // options in raw: Gtk::CheckButton* raw_expos; @@ -160,6 +236,9 @@ public: void rawToggled (); void advancedToggled (); void locallabToggled (); + + void updateSpotWidget(const rtengine::procparams::ProcParams* pp); + void partialSpotUpdated(const UpdateStatus status); }; #endif diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index 8781fe97a..a2597c2d5 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -343,6 +343,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); } partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); + partialProfileDlg->updateSpotWidget(toSave->pparams); int i = partialProfileDlg->run(); partialProfileDlg->hide(); @@ -417,6 +418,7 @@ void ProfilePanel::copy_clicked (GdkEventButton* event) partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); } partialProfileDlg->set_title(M("PROFILEPANEL_COPYPPASTE")); + partialProfileDlg->updateSpotWidget(toSave->pparams); int i = partialProfileDlg->run(); partialProfileDlg->hide(); @@ -482,19 +484,6 @@ void ProfilePanel::load_clicked (GdkEventButton* event) if (result == Gtk::RESPONSE_OK) { Glib::ustring fname = dialog.get_filename(); printf("fname=%s\n", fname.c_str()); - if (event->state & Gdk::CONTROL_MASK) { - // opening the partial paste dialog window - if(!partialProfileDlg) { - partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); - } - partialProfileDlg->set_title(M("PROFILEPANEL_LOADPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - - if (i != Gtk::RESPONSE_OK) { - return; - } - } bool customCreated = false; @@ -532,6 +521,17 @@ void ProfilePanel::load_clicked (GdkEventButton* event) if(!partialProfileDlg) { partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); } + + // opening the partial paste dialog window + partialProfileDlg->set_title(M("PROFILEPANEL_LOADPPASTE")); + partialProfileDlg->updateSpotWidget(&pp); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + + if (i != Gtk::RESPONSE_OK) { + return; + } + partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active() ? custom->pedited : nullptr, &pp, &pe); } else { // custom.pparams = loadedFile.pparams filtered by ( loadedFile.pedited ) @@ -568,19 +568,6 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) return; } - if (event->state & Gdk::CONTROL_MASK) { - if(!partialProfileDlg) { - partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); - } - partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - - if (i != Gtk::RESPONSE_OK) { - return; - } - } - bool prevState = changeconn.block(true); if (!custom) { @@ -589,9 +576,9 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) if (isLastSavedSelected()) { *custom->pparams = *lastsaved->pparams; - // Setting LocallabSpotEdited number coherent with nbspot number in lastsaved->pparams + // Setting LocallabSpotEdited number coherent with spots number in lastsaved->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(false)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(false)); } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); @@ -599,9 +586,9 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) const PartialProfile* partProfile = ProfileStore::getInstance()->getProfile (entry); *custom->pparams = *partProfile->pparams; - // Setting LocallabSpotEdited number coherent with nbspot number in partProfile->pparams + // Setting LocallabSpotEdited number coherent with spots number in partProfile->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(false)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(false)); } } @@ -617,9 +604,9 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) if (isLastSavedSelected()) { *custom->pparams = *lastsaved->pparams; - // Setting LocallabSpotEdited number coherent with nbspot number in lastsaved->pparams + // Setting LocallabSpotEdited number coherent with spots number in lastsaved->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); @@ -627,9 +614,9 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) const PartialProfile* partProfile = ProfileStore::getInstance()->getProfile (entry); *custom->pparams = *partProfile->pparams; - // Setting LocallabSpotEdited number coherent with nbspot number in partProfile->pparams + // Setting LocallabSpotEdited number coherent with spots number in partProfile->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); } } } @@ -656,6 +643,16 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) if(!partialProfileDlg) { partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); } + + partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); + partialProfileDlg->updateSpotWidget(&pp); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + + if (i != Gtk::RESPONSE_OK) { + return; + } + partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active() ? custom->pedited : nullptr, &pp, &pe); } else { // custom.pparams = clipboard.pparams filtered by ( clipboard.pedited ) @@ -672,18 +669,28 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) if(!partialProfileDlg) { partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); } + + partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); + partialProfileDlg->updateSpotWidget(&pp); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + + if (i != Gtk::RESPONSE_OK) { + return; + } + partialProfileDlg->applyPaste (custom->pparams, nullptr, &pp, nullptr); - // Setting LocallabSpotEdited number coherent with nbspot number in custom->pparams + // Setting LocallabSpotEdited number coherent with spots number in custom->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); } else { // custom.pparams = clipboard.pparams non filtered *custom->pparams = pp; - // Setting LocallabSpotEdited number coherent with nbspot number in custom->pparams + // Setting LocallabSpotEdited number coherent with spots number in custom->pparams custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(custom->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + custom->pedited->locallab.spots.resize(custom->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); } } @@ -732,8 +739,8 @@ void ProfilePanel::selection_changed () if (fillMode->get_active() && s->pedited) { ParamsEdited pe(true); - // Setting LocallabSpotEdited number coherent with nbspot number in s->pparams - pe.locallab.spots.resize(s->pparams->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + // Setting LocallabSpotEdited number coherent with spots number in s->pparams + pe.locallab.spots.resize(s->pparams->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); PartialProfile s2(s->pparams, &pe, false); changeTo (&s2, pse->label + "+"); @@ -774,9 +781,9 @@ void ProfilePanel::procParamsChanged( *custom->pparams = *p; - // Setting LocallabSpotEdited number coherent with nbspot number in p + // Setting LocallabSpotEdited number coherent with spots number in p custom->pedited->locallab.spots.clear(); - custom->pedited->locallab.spots.resize(p->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + custom->pedited->locallab.spots.resize(p->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); } void ProfilePanel::clearParamChanges() @@ -812,8 +819,8 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams if (lastSaved) { ParamsEdited* pe = new ParamsEdited(true); - // Setting LocallabSpotEdited number coherent with lastSaved->locallab.nbspot (initialized at true such as pe) - pe->locallab.spots.resize(lastSaved->locallab.nbspot, new LocallabParamsEdited::LocallabSpotEdited(true)); + // Setting LocallabSpotEdited number coherent with lastSaved->locallab spots number (initialized at true such as pe) + pe->locallab.spots.resize(lastSaved->locallab.spots.size(), new LocallabParamsEdited::LocallabSpotEdited(true)); // copying the provided last saved profile to ProfilePanel::lastsaved lastsaved = new PartialProfile(lastSaved, pe); }