Collection of CSS and GUI improvements, cleanup of main CSS theme, introduction of highlight for enabled module. Primary change is the modification of the module titles to better distinguish modules that are on or off. The text of a disabled module is now less bright, the corresponding icon is a slightly smaller version of the power icon. When activating the module, the text turns brighter and the icon slightly bigger and also brighter. Thanks to @TechXavAL for the icon work. Secondary changes are related to the margins around several GUI elements, padding within elements and some accompanying borders. These changes hopefully make it easier to distinguish the various (sometimes crowded) GUI elements of modules. The panels have gotten a slightly 'outset' look. Nested panels have a changed look where deeper nesting increases the background brightness slightly, instead of darkening it (old behaviour). This is done without a strong decrease in contrast. The old theme is available as a legacy option. Due to hardcoded GUI changes needed for the new theme, the legacy version is not a 100% exact replicate. The @TooWaBoo theme's may also be slightly affected.
835 lines
28 KiB
C++
835 lines
28 KiB
C++
/*
|
|
* This file is part of RawTherapee.
|
|
*
|
|
* Copyright (c) 2012 Oliver Duis <oduis@oliverduis.de>
|
|
*
|
|
* RawTherapee is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* RawTherapee is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <map>
|
|
#include <set>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#include <glibmm/ustring.h>
|
|
|
|
#include "lensprofile.h"
|
|
|
|
#include "guiutils.h"
|
|
#include "rtimage.h"
|
|
#include "options.h"
|
|
|
|
#include "../rtengine/lcp.h"
|
|
#include "../rtengine/procparams.h"
|
|
#include "../rtengine/rtlensfun.h"
|
|
|
|
using namespace rtengine;
|
|
using namespace rtengine::procparams;
|
|
|
|
LensProfilePanel::LensProfilePanel() :
|
|
FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")),
|
|
lcModeChanged(false),
|
|
lcpFileChanged(false),
|
|
useDistChanged(false),
|
|
useVignChanged(false),
|
|
useCAChanged(false),
|
|
useLensfunChanged(false),
|
|
lensfunAutoChanged(false),
|
|
lensfunCameraChanged(false),
|
|
lensfunLensChanged(false),
|
|
allowFocusDep(true),
|
|
isRaw(true),
|
|
metadata(nullptr),
|
|
modesGrid(Gtk::manage(new Gtk::Grid())),
|
|
distGrid(Gtk::manage((new Gtk::Grid()))),
|
|
corrUnchangedRB(Gtk::manage((new Gtk::RadioButton(M("GENERAL_UNCHANGED"))))),
|
|
corrOffRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("GENERAL_NONE"))))),
|
|
corrLensfunAutoRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_AUTOMATCH"))))),
|
|
corrLensfunManualRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_MANUAL"))))),
|
|
corrLcpFileRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_LCPFILE"))))),
|
|
corrLcpFileChooser(Gtk::manage((new MyFileChooserButton(M("TP_LENSPROFILE_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)))),
|
|
lensfunCamerasLbl(Gtk::manage((new Gtk::Label(M("EXIFFILTER_CAMERA"))))),
|
|
lensfunCameras(Gtk::manage((new MyComboBox()))),
|
|
lensfunLensesLbl(Gtk::manage((new Gtk::Label(M("EXIFFILTER_LENS"))))),
|
|
lensfunLenses(Gtk::manage((new MyComboBox()))),
|
|
warning(Gtk::manage(new RTImage("warning.png"))),
|
|
ckbUseDist(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_GEOMETRIC"))))),
|
|
ckbUseVign(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_VIGNETTING"))))),
|
|
ckbUseCA(Gtk::manage((new Gtk::CheckButton(M("TP_LENSPROFILE_USE_CA")))))
|
|
{
|
|
if (!lf) {
|
|
lf = new LFDbHelper();
|
|
}
|
|
|
|
// Main containers:
|
|
|
|
Gtk::Frame *nodesFrame = Gtk::manage(new Gtk::Frame(M("TP_LENSPROFILE_MODE_HEADER")));
|
|
nodesFrame->set_label_align (0.025, 0.5);
|
|
|
|
modesGrid->get_style_context()->add_class("grid-spacing");
|
|
setExpandAlignProperties(modesGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
|
|
|
Gtk::Frame *distFrame = Gtk::manage(new Gtk::Frame(M("TP_LENSPROFILE_USE_HEADER")));
|
|
distFrame->set_label_align (0.025, 0.5);
|
|
|
|
distGrid->get_style_context()->add_class("grid-spacing");
|
|
setExpandAlignProperties(distGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
|
|
|
// Mode choice widgets:
|
|
|
|
setExpandAlignProperties(corrLcpFileChooser, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
|
|
|
// Manually-selected profile widgets:
|
|
|
|
setExpandAlignProperties(lensfunCamerasLbl, false, false, Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
|
|
|
|
lensfunCameras->set_model(lf->lensfunCameraModel);
|
|
lensfunCameras->pack_start(lf->lensfunModelCam.model);
|
|
lensfunCameras->setPreferredWidth(50, 120);
|
|
setExpandAlignProperties(lensfunCameras, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
|
|
|
Gtk::CellRendererText* const camerasCellRenderer = static_cast<Gtk::CellRendererText*>(lensfunCameras->get_first_cell());
|
|
camerasCellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
|
|
camerasCellRenderer->property_ellipsize_set() = true;
|
|
|
|
setExpandAlignProperties(lensfunLensesLbl, false, false, Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
|
|
|
|
lensfunLenses->set_model(lf->lensfunLensModel);
|
|
lensfunLenses->pack_start(lf->lensfunModelLens.prettylens);
|
|
lensfunLenses->setPreferredWidth(50, 120);
|
|
setExpandAlignProperties(lensfunLenses, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
|
|
|
Gtk::CellRendererText* const lensesCellRenderer = static_cast<Gtk::CellRendererText*>(lensfunLenses->get_first_cell());
|
|
lensesCellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
|
|
lensesCellRenderer->property_ellipsize_set() = true;
|
|
|
|
warning->set_tooltip_text(M("TP_LENSPROFILE_LENS_WARNING"));
|
|
warning->hide();
|
|
|
|
// LCP file filter config:
|
|
|
|
const Glib::RefPtr<Gtk::FileFilter> filterLCP = Gtk::FileFilter::create();
|
|
filterLCP->set_name(M("FILECHOOSER_FILTER_LCP"));
|
|
filterLCP->add_pattern("*.lcp");
|
|
filterLCP->add_pattern("*.LCP");
|
|
corrLcpFileChooser->add_filter(filterLCP);
|
|
|
|
const Glib::ustring defDir = LCPStore::getInstance()->getDefaultCommonDirectory();
|
|
|
|
if (!defDir.empty()) {
|
|
#ifdef WIN32
|
|
corrLcpFileChooser->set_show_hidden(true); // ProgramData is hidden on Windows
|
|
#endif
|
|
corrLcpFileChooser->set_current_folder(defDir);
|
|
} else if (!options.lastLensProfileDir.empty()) {
|
|
corrLcpFileChooser->set_current_folder(options.lastLensProfileDir);
|
|
}
|
|
|
|
bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir);
|
|
|
|
// Choice of properties to correct, applicable to all modes:
|
|
|
|
// Populate modes grid:
|
|
|
|
modesGrid->attach(*corrOffRB, 0, 0, 3, 1);
|
|
modesGrid->attach(*corrLensfunAutoRB, 0, 1, 3, 1);
|
|
modesGrid->attach(*corrLensfunManualRB, 0, 2, 3, 1);
|
|
|
|
modesGrid->attach(*lensfunCamerasLbl, 0, 3, 1, 1);
|
|
modesGrid->attach(*lensfunCameras, 1, 3, 1, 1);
|
|
modesGrid->attach(*lensfunLensesLbl, 0, 4, 1, 1);
|
|
modesGrid->attach(*lensfunLenses, 1, 4, 1, 1);
|
|
modesGrid->attach(*warning, 2, 3, 1, 2);
|
|
|
|
modesGrid->attach(*corrLcpFileRB, 0, 5, 1, 1);
|
|
modesGrid->attach(*corrLcpFileChooser, 1, 5, 1, 1);
|
|
|
|
// Populate distortions grid:
|
|
|
|
distGrid->attach(*ckbUseDist, 0, 0, 1, 1);
|
|
distGrid->attach(*ckbUseVign, 0, 1, 1, 1);
|
|
distGrid->attach(*ckbUseCA, 0, 2, 1, 1);
|
|
|
|
// Attach grids:
|
|
nodesFrame->add(*modesGrid);
|
|
distFrame->add(*distGrid);
|
|
|
|
pack_start(*nodesFrame, Gtk::PACK_EXPAND_WIDGET);
|
|
pack_start(*distFrame, Gtk::PACK_EXPAND_WIDGET);
|
|
|
|
// Signals:
|
|
|
|
conLCPFile = corrLcpFileChooser->signal_file_set().connect(sigc::mem_fun(*this, &LensProfilePanel::onLCPFileChanged));
|
|
conUseDist = ckbUseDist->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseDistChanged));
|
|
ckbUseVign->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged));
|
|
ckbUseCA->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged));
|
|
|
|
lensfunCameras->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunCameraChanged));
|
|
lensfunLenses->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunLensChanged));
|
|
corrOffRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrOffRB));
|
|
corrLensfunAutoRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunAutoRB));
|
|
corrLensfunManualRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunManualRB));
|
|
corrLcpFileRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLcpFileRB));
|
|
}
|
|
|
|
void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited)
|
|
{
|
|
disableListener();
|
|
conUseDist.block(true);
|
|
|
|
// corrLensfunAutoRB->set_sensitive(true);
|
|
|
|
switch (pp->lensProf.lcMode) {
|
|
case procparams::LensProfParams::LcMode::LCP: {
|
|
corrLcpFileRB->set_active(true);
|
|
setManualParamsVisibility(false);
|
|
break;
|
|
}
|
|
|
|
case procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH: {
|
|
corrLensfunAutoRB->set_active(true);
|
|
if (batchMode) {
|
|
setManualParamsVisibility(false);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case procparams::LensProfParams::LcMode::LENSFUNMANUAL: {
|
|
corrLensfunManualRB->set_active(true);
|
|
break;
|
|
}
|
|
|
|
case procparams::LensProfParams::LcMode::NONE: {
|
|
corrOffRB->set_active(true);
|
|
setManualParamsVisibility(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pp->lensProf.lcpFile.empty()) {
|
|
const Glib::ustring lastFolder = corrLcpFileChooser->get_current_folder();
|
|
corrLcpFileChooser->set_current_folder(lastFolder);
|
|
corrLcpFileChooser->unselect_all();
|
|
bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir);
|
|
updateDisabled(false);
|
|
}
|
|
else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) {
|
|
corrLcpFileChooser->set_filename(pp->lensProf.lcpFile);
|
|
|
|
if (corrLcpFileRB->get_active()) {
|
|
updateDisabled(true);
|
|
}
|
|
}
|
|
else {
|
|
corrLcpFileChooser->unselect_filename(corrLcpFileChooser->get_filename());
|
|
updateDisabled(false);
|
|
}
|
|
|
|
const LFDatabase* const db = LFDatabase::getInstance();
|
|
LFCamera c;
|
|
|
|
if (pp->lensProf.lfAutoMatch()) {
|
|
if (metadata) {
|
|
c = db->findCamera(metadata->getMake(), metadata->getModel());
|
|
setLensfunCamera(c.getMake(), c.getModel());
|
|
}
|
|
} else if (pp->lensProf.lfManual()) {
|
|
setLensfunCamera(pp->lensProf.lfCameraMake, pp->lensProf.lfCameraModel);
|
|
}
|
|
|
|
if (pp->lensProf.lfAutoMatch()) {
|
|
if (metadata) {
|
|
const LFLens l = db->findLens(c, metadata->getLens());
|
|
setLensfunLens(l.getLens());
|
|
}
|
|
} else if (pp->lensProf.lfManual()) {
|
|
setLensfunLens(pp->lensProf.lfLens);
|
|
}
|
|
|
|
|
|
/*
|
|
if (!batchMode && !checkLensfunCanCorrect(true)) {
|
|
if (corrLensfunAutoRB->get_active()) {
|
|
corrOffRB->set_active(true);
|
|
}
|
|
|
|
corrLensfunAutoRB->set_sensitive(false);
|
|
}
|
|
|
|
if (!batchMode && corrLensfunManualRB->get_active() && !checkLensfunCanCorrect(false)) {
|
|
corrOffRB->set_active(true);
|
|
}
|
|
*/
|
|
|
|
ckbUseDist->set_active(pp->lensProf.useDist);
|
|
ckbUseVign->set_active(pp->lensProf.useVign);
|
|
ckbUseCA->set_active(pp->lensProf.useCA);
|
|
|
|
if (pedited) {
|
|
corrUnchangedRB->set_active(!pedited->lensProf.lcMode);
|
|
ckbUseDist->set_inconsistent(!pedited->lensProf.useDist);
|
|
ckbUseVign->set_inconsistent(!pedited->lensProf.useVign);
|
|
ckbUseCA->set_inconsistent(!pedited->lensProf.useCA);
|
|
|
|
if (!pedited->lensProf.lfCameraMake || !pedited->lensProf.lfCameraModel) {
|
|
setLensfunCamera("", "");
|
|
}
|
|
if (!pedited->lensProf.lfLens) {
|
|
setLensfunLens("");
|
|
}
|
|
|
|
ckbUseDist->set_sensitive(true);
|
|
ckbUseVign->set_sensitive(true);
|
|
ckbUseCA->set_sensitive(true);
|
|
}
|
|
|
|
lcModeChanged = lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false;
|
|
useLensfunChanged = lensfunAutoChanged = lensfunCameraChanged = lensfunLensChanged = false;
|
|
|
|
updateLensfunWarning();
|
|
enableListener();
|
|
conUseDist.block(false);
|
|
}
|
|
|
|
void LensProfilePanel::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
|
|
{
|
|
if (corrLcpFileRB->get_active()) {
|
|
pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LCP;
|
|
}
|
|
else if (corrLensfunManualRB->get_active()) {
|
|
pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNMANUAL;
|
|
}
|
|
else if (corrLensfunAutoRB->get_active()) {
|
|
pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNAUTOMATCH;
|
|
}
|
|
else if (corrOffRB->get_active()) {
|
|
pp->lensProf.lcMode = procparams::LensProfParams::LcMode::NONE;
|
|
}
|
|
|
|
if (LCPStore::getInstance()->isValidLCPFileName(corrLcpFileChooser->get_filename())) {
|
|
pp->lensProf.lcpFile = corrLcpFileChooser->get_filename();
|
|
} else {
|
|
pp->lensProf.lcpFile = "";
|
|
}
|
|
|
|
pp->lensProf.useDist = ckbUseDist->get_active();
|
|
pp->lensProf.useVign = ckbUseVign->get_active();
|
|
pp->lensProf.useCA = ckbUseCA->get_active();
|
|
|
|
const auto itc = lensfunCameras->get_active();
|
|
|
|
if (itc && !corrLensfunAutoRB->get_active()) {
|
|
pp->lensProf.lfCameraMake = (*itc)[lf->lensfunModelCam.make];
|
|
pp->lensProf.lfCameraModel = (*itc)[lf->lensfunModelCam.model];
|
|
} else {
|
|
pp->lensProf.lfCameraMake = "";
|
|
pp->lensProf.lfCameraModel = "";
|
|
}
|
|
|
|
const auto itl = lensfunLenses->get_active();
|
|
|
|
if (itl && !corrLensfunAutoRB->get_active()) {
|
|
pp->lensProf.lfLens = (*itl)[lf->lensfunModelLens.lens];
|
|
} else {
|
|
pp->lensProf.lfLens = "";
|
|
}
|
|
|
|
if (pedited) {
|
|
pedited->lensProf.lcMode = lcModeChanged;
|
|
pedited->lensProf.lcpFile = lcpFileChanged;
|
|
pedited->lensProf.useDist = useDistChanged;
|
|
pedited->lensProf.useVign = useVignChanged;
|
|
pedited->lensProf.useCA = useCAChanged;
|
|
pedited->lensProf.useLensfun = useLensfunChanged;
|
|
pedited->lensProf.lfAutoMatch = lensfunAutoChanged;
|
|
pedited->lensProf.lfCameraMake = lensfunCameraChanged;
|
|
pedited->lensProf.lfCameraModel = lensfunCameraChanged;
|
|
pedited->lensProf.lfLens = lensfunLensChanged;
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMeta)
|
|
{
|
|
if ((!raw || pMeta->getFocusDist() <= 0) && !batchMode) {
|
|
disableListener();
|
|
|
|
// CA is very focus layer dependent, otherwise it might even worsen things
|
|
allowFocusDep = false;
|
|
ckbUseCA->set_active(false);
|
|
ckbUseCA->set_sensitive(false);
|
|
|
|
enableListener();
|
|
}
|
|
|
|
isRaw = raw;
|
|
metadata = pMeta;
|
|
}
|
|
|
|
void LensProfilePanel::onLCPFileChanged()
|
|
{
|
|
lcpFileChanged = true;
|
|
const bool valid = LCPStore::getInstance()->isValidLCPFileName(corrLcpFileChooser->get_filename());
|
|
updateDisabled(valid);
|
|
|
|
if (listener) {
|
|
if (valid) {
|
|
disableListener();
|
|
corrLcpFileRB->set_active(true);
|
|
enableListener();
|
|
}
|
|
|
|
listener->panelChanged(EvLCPFile, Glib::path_get_basename(corrLcpFileChooser->get_filename()));
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::onUseDistChanged()
|
|
{
|
|
useDistChanged = true;
|
|
if (ckbUseDist->get_inconsistent()) {
|
|
ckbUseDist->set_inconsistent(false);
|
|
ckbUseDist->set_active(false);
|
|
}
|
|
|
|
if (listener) {
|
|
listener->panelChanged(EvLCPUseDist, ckbUseDist->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::onUseVignChanged()
|
|
{
|
|
useVignChanged = true;
|
|
if (ckbUseVign->get_inconsistent()) {
|
|
ckbUseVign->set_inconsistent(false);
|
|
ckbUseVign->set_active(false);
|
|
}
|
|
|
|
if (listener) {
|
|
listener->panelChanged(EvLCPUseVign, ckbUseVign->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::onUseCAChanged()
|
|
{
|
|
useCAChanged = true;
|
|
if (ckbUseCA->get_inconsistent()) {
|
|
ckbUseCA->set_inconsistent(false);
|
|
ckbUseCA->set_active(false);
|
|
}
|
|
|
|
if (listener) {
|
|
listener->panelChanged(EvLCPUseCA, ckbUseCA->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::setBatchMode(bool yes)
|
|
{
|
|
FoldableToolPanel::setBatchMode(yes);
|
|
|
|
corrUnchangedRB->set_group(corrGroup);
|
|
modesGrid->attach_next_to(*corrUnchangedRB, Gtk::POS_TOP, 3, 1);
|
|
corrUnchangedRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrUnchangedRB));
|
|
corrUnchangedRB->set_active(true);
|
|
}
|
|
|
|
void LensProfilePanel::onLensfunCameraChanged()
|
|
{
|
|
const auto iter = lensfunCameras->get_active();
|
|
|
|
if (iter) {
|
|
lensfunCameraChanged = true;
|
|
|
|
if (listener) {
|
|
disableListener();
|
|
corrLensfunManualRB->set_active(true);
|
|
enableListener();
|
|
|
|
const Glib::ustring name = (*iter)[lf->lensfunModelCam.model];
|
|
listener->panelChanged(EvLensCorrLensfunCamera, name);
|
|
}
|
|
}
|
|
|
|
updateLensfunWarning();
|
|
}
|
|
|
|
void LensProfilePanel::onLensfunLensChanged()
|
|
{
|
|
const auto iter = lensfunLenses->get_active();
|
|
|
|
if (iter) {
|
|
lensfunLensChanged = true;
|
|
|
|
if (listener) {
|
|
disableListener();
|
|
corrLensfunManualRB->set_active(true);
|
|
enableListener();
|
|
|
|
const Glib::ustring name = (*iter)[lf->lensfunModelLens.prettylens];
|
|
listener->panelChanged(EvLensCorrLensfunLens, name);
|
|
}
|
|
}
|
|
|
|
updateLensfunWarning();
|
|
}
|
|
|
|
void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged)
|
|
{
|
|
if (rbChanged->get_active()) {
|
|
// because the method gets called for the enabled AND the disabled RadioButton, we do the processing only for the enabled one
|
|
Glib::ustring mode;
|
|
|
|
if (rbChanged == corrOffRB) {
|
|
lcModeChanged = true;
|
|
useLensfunChanged = true;
|
|
lensfunAutoChanged = true;
|
|
lcpFileChanged = false;
|
|
|
|
ckbUseDist->set_sensitive(false);
|
|
ckbUseVign->set_sensitive(false);
|
|
ckbUseCA->set_sensitive(false);
|
|
|
|
mode = M("GENERAL_NONE");
|
|
|
|
} else if (rbChanged == corrLensfunAutoRB) {
|
|
lcModeChanged = true;
|
|
useLensfunChanged = true;
|
|
lensfunAutoChanged = true;
|
|
lensfunCameraChanged = true;
|
|
lensfunLensChanged = true;
|
|
lcpFileChanged = false;
|
|
|
|
ckbUseDist->set_sensitive(true);
|
|
ckbUseVign->set_sensitive(true);
|
|
ckbUseCA->set_sensitive(true);
|
|
|
|
|
|
const bool disabled = disableListener();
|
|
if (batchMode) {
|
|
setLensfunCamera("", "");
|
|
setLensfunLens("");
|
|
} else if (metadata) {
|
|
const LFDatabase* const db = LFDatabase::getInstance();
|
|
const LFCamera c = db->findCamera(metadata->getMake(), metadata->getModel());
|
|
const LFLens l = db->findLens(c, metadata->getLens());
|
|
setLensfunCamera(c.getMake(), c.getModel());
|
|
setLensfunLens(l.getLens());
|
|
}
|
|
if (disabled) {
|
|
enableListener();
|
|
}
|
|
|
|
mode = M("TP_LENSPROFILE_CORRECTION_AUTOMATCH");
|
|
|
|
} else if (rbChanged == corrLensfunManualRB) {
|
|
lcModeChanged = true;
|
|
useLensfunChanged = true;
|
|
lensfunAutoChanged = true;
|
|
lensfunCameraChanged = true;
|
|
lensfunLensChanged = true;
|
|
lcpFileChanged = false;
|
|
|
|
ckbUseDist->set_sensitive(true);
|
|
ckbUseVign->set_sensitive(true);
|
|
ckbUseCA->set_sensitive(false);
|
|
|
|
mode = M("TP_LENSPROFILE_CORRECTION_MANUAL");
|
|
|
|
} else if (rbChanged == corrLcpFileRB) {
|
|
lcModeChanged = true;
|
|
useLensfunChanged = true;
|
|
lensfunAutoChanged = true;
|
|
lcpFileChanged = true;
|
|
|
|
updateDisabled(true);
|
|
|
|
mode = M("TP_LENSPROFILE_CORRECTION_LCPFILE");
|
|
|
|
} else if (rbChanged == corrUnchangedRB) {
|
|
lcModeChanged = false;
|
|
useLensfunChanged = false;
|
|
lensfunAutoChanged = false;
|
|
lcpFileChanged = false;
|
|
lensfunCameraChanged = false;
|
|
lensfunLensChanged = false;
|
|
|
|
ckbUseDist->set_sensitive(true);
|
|
ckbUseVign->set_sensitive(true);
|
|
ckbUseCA->set_sensitive(true);
|
|
|
|
mode = M("GENERAL_UNCHANGED");
|
|
}
|
|
|
|
updateLensfunWarning();
|
|
|
|
if (rbChanged == corrLensfunManualRB || (!batchMode && rbChanged == corrLensfunAutoRB)) {
|
|
setManualParamsVisibility(true);
|
|
} else {
|
|
setManualParamsVisibility(false);
|
|
}
|
|
|
|
if (listener) {
|
|
listener->panelChanged(EvLensCorrMode, mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// LFDbHelper
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LensProfilePanel::LFDbHelper::LFDbHelper()
|
|
{
|
|
lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam);
|
|
lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens);
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp parallel sections if (!settings->verbose)
|
|
#endif
|
|
{
|
|
#ifdef _OPENMP
|
|
#pragma omp section
|
|
#endif
|
|
{
|
|
fillLensfunCameras();
|
|
}
|
|
#ifdef _OPENMP
|
|
#pragma omp section
|
|
#endif
|
|
{
|
|
fillLensfunLenses();
|
|
}
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::LFDbHelper::fillLensfunCameras()
|
|
{
|
|
if (settings->verbose) {
|
|
std::cout << "LENSFUN, scanning cameras:" << std::endl;
|
|
}
|
|
|
|
std::map<Glib::ustring, std::set<Glib::ustring>> camnames;
|
|
const auto camlist = LFDatabase::getInstance()->getCameras();
|
|
|
|
for (const auto& c : camlist) {
|
|
camnames[c.getMake()].insert(c.getModel());
|
|
|
|
if (settings->verbose) {
|
|
std::cout << " found: " << c.getDisplayString().c_str() << std::endl;
|
|
}
|
|
}
|
|
|
|
for (const auto& p : camnames) {
|
|
Gtk::TreeModel::Row row = *(lensfunCameraModel->append());
|
|
row[lensfunModelCam.make] = p.first;
|
|
row[lensfunModelCam.model] = p.first;
|
|
|
|
for (const auto& c : p.second) {
|
|
Gtk::TreeModel::Row child = *(lensfunCameraModel->append(row.children()));
|
|
child[lensfunModelCam.make] = p.first;
|
|
child[lensfunModelCam.model] = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::LFDbHelper::fillLensfunLenses()
|
|
{
|
|
if (settings->verbose) {
|
|
std::cout << "LENSFUN, scanning lenses:" << std::endl;
|
|
}
|
|
|
|
std::map<Glib::ustring, std::set<Glib::ustring>> lenses;
|
|
const auto lenslist = LFDatabase::getInstance()->getLenses();
|
|
|
|
for (const auto& l : lenslist) {
|
|
const auto& name = l.getLens();
|
|
const auto& make = l.getMake();
|
|
lenses[make].insert(name);
|
|
|
|
if (settings->verbose) {
|
|
std::cout << " found: " << l.getDisplayString().c_str() << std::endl;
|
|
}
|
|
}
|
|
|
|
for (const auto& p : lenses) {
|
|
Gtk::TreeModel::Row row = *(lensfunLensModel->append());
|
|
row[lensfunModelLens.lens] = p.first;
|
|
row[lensfunModelLens.prettylens] = p.first;
|
|
|
|
for (auto &c : p.second) {
|
|
Gtk::TreeModel::Row child = *(lensfunLensModel->append(row.children()));
|
|
child[lensfunModelLens.lens] = c;
|
|
|
|
if (c.find(p.first, p.first.size() + 1) == p.first.size() + 1) {
|
|
child[lensfunModelLens.prettylens] = c.substr(p.first.size() + 1);
|
|
} else {
|
|
child[lensfunModelLens.prettylens] = c;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::updateDisabled(bool enable)
|
|
{
|
|
if (!batchMode) {
|
|
ckbUseDist->set_sensitive(enable);
|
|
ckbUseVign->set_sensitive(enable && isRaw);
|
|
ckbUseCA->set_sensitive(enable && allowFocusDep);
|
|
}
|
|
}
|
|
|
|
bool LensProfilePanel::setLensfunCamera(const Glib::ustring& make, const Glib::ustring& model)
|
|
{
|
|
if (!make.empty() && !model.empty()) {
|
|
const auto camera_it = lensfunCameras->get_active();
|
|
|
|
if (camera_it && (*camera_it)[lf->lensfunModelCam.make] == make && (*camera_it)[lf->lensfunModelCam.model] == model) {
|
|
return true;
|
|
}
|
|
|
|
// search for the active row
|
|
for (const auto& row : lf->lensfunCameraModel->children()) {
|
|
if (row[lf->lensfunModelCam.make] == make) {
|
|
const auto& c = row.children();
|
|
|
|
for (auto model_it = c.begin(), end = c.end(); model_it != end; ++model_it) {
|
|
const auto& childrow = *model_it;
|
|
|
|
if (childrow[lf->lensfunModelCam.model] == model) {
|
|
lensfunCameras->set_active(model_it);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
lensfunCameras->set_active(-1);
|
|
return false;
|
|
}
|
|
|
|
bool LensProfilePanel::setLensfunLens(const Glib::ustring& lens)
|
|
{
|
|
if (!lens.empty()) {
|
|
const auto lens_it = lensfunLenses->get_active();
|
|
|
|
if (lens_it && (*lens_it)[lf->lensfunModelLens.lens] == lens) {
|
|
return true;
|
|
}
|
|
|
|
bool first_maker_found = false;
|
|
|
|
for (const auto& row : lf->lensfunLensModel->children()) {
|
|
if (lens.find(row[lf->lensfunModelLens.lens]) == 0) {
|
|
const auto& c = row.children();
|
|
|
|
for (auto model_it = c.begin(), end = c.end(); model_it != end; ++model_it) {
|
|
const auto& childrow = *model_it;
|
|
|
|
if (childrow[lf->lensfunModelLens.lens] == lens) {
|
|
lensfunLenses->set_active(model_it);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// we do not break immediately here, because there might be multiple makers
|
|
// sharing the same prefix (e.g. "Leica" and "Leica Camera AG").
|
|
// therefore, we break below when the lens doesn't match any of them
|
|
first_maker_found = true;
|
|
} else if (first_maker_found) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
lensfunLenses->set_active(-1);
|
|
return false;
|
|
}
|
|
|
|
bool LensProfilePanel::checkLensfunCanCorrect(bool automatch)
|
|
{
|
|
if (!metadata) {
|
|
return false;
|
|
}
|
|
|
|
rtengine::procparams::ProcParams lpp;
|
|
write(&lpp);
|
|
const std::unique_ptr<LFModifier> mod(LFDatabase::getInstance()->findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1));
|
|
return static_cast<bool>(mod);
|
|
}
|
|
|
|
void LensProfilePanel::setManualParamsVisibility(bool setVisible)
|
|
{
|
|
if (setVisible) {
|
|
lensfunCamerasLbl->show();
|
|
lensfunCameras->show();
|
|
lensfunLensesLbl->show();
|
|
lensfunLenses->show();
|
|
updateLensfunWarning();
|
|
} else {
|
|
lensfunCamerasLbl->hide();
|
|
lensfunCameras->hide();
|
|
lensfunLensesLbl->hide();
|
|
lensfunLenses->hide();
|
|
warning->hide();
|
|
}
|
|
}
|
|
|
|
void LensProfilePanel::updateLensfunWarning()
|
|
{
|
|
warning->hide();
|
|
|
|
if (corrLensfunManualRB->get_active() || corrLensfunAutoRB->get_active()) {
|
|
const LFDatabase* const db = LFDatabase::getInstance();
|
|
|
|
const auto itc = lensfunCameras->get_active();
|
|
|
|
if (!itc) {
|
|
return;
|
|
}
|
|
|
|
const LFCamera c = db->findCamera((*itc)[lf->lensfunModelCam.make], (*itc)[lf->lensfunModelCam.model]);
|
|
const auto itl = lensfunLenses->get_active();
|
|
|
|
if (!itl) {
|
|
return;
|
|
}
|
|
|
|
const LFLens l = db->findLens(LFCamera(), (*itl)[lf->lensfunModelLens.lens]);
|
|
const float lenscrop = l.getCropFactor();
|
|
const float camcrop = c.getCropFactor();
|
|
|
|
if (lenscrop <= 0 || camcrop <= 0 || lenscrop / camcrop >= 1.01f) {
|
|
warning->show();
|
|
}
|
|
|
|
ckbUseVign->set_sensitive(l.hasVignettingCorrection());
|
|
ckbUseDist->set_sensitive(l.hasDistortionCorrection());
|
|
ckbUseCA->set_sensitive(l.hasCACorrection());
|
|
|
|
if (!isRaw || !l.hasVignettingCorrection()) {
|
|
ckbUseVign->set_active(false);
|
|
}
|
|
|
|
if (!l.hasDistortionCorrection()) {
|
|
ckbUseDist->set_active(false);
|
|
}
|
|
|
|
if (!l.hasCACorrection()) {
|
|
ckbUseCA->set_active(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
LensProfilePanel::LFDbHelper* LensProfilePanel::lf(nullptr);
|