1 /*******************************************************************************
2 **
3 ** Photivo
4 **
5 ** Copyright (C) 2008 Jos De Laender <jos.de_laender@telenet.be>
6 ** Copyright (C) 2010-2011 Michael Munzert <mail@mm-log.com>
7 ** Copyright (C) 2013 Alexander Tzyganenko <tz@fast-report.com>
8 **
9 ** This file is part of Photivo.
10 **
11 ** Photivo is free software: you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License version 3
13 ** as published by the Free Software Foundation.
14 **
15 ** Photivo is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ** GNU General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with Photivo.  If not, see <http://www.gnu.org/licenses/>.
22 **
23 *******************************************************************************/
24 
25 #include "ptSettings.h"
26 #include "ptError.h"
27 #include "ptDcRaw.h"
28 #include "ptRGBTemperature.h"
29 #include "ptGuiOptions.h"
30 #include "filemgmt/ptFileMgrConstants.h"
31 #include <filters/ptFilterUids.h>
32 
33 #include <cassert>
34 
35 //==============================================================================
36 
37 // Macro for inserting a key into the hash and checking it is a new one.
38 #define M_InsertKeyIntoHash(Key,Item)                      \
39   if (m_Hash.contains(Key)) {                              \
40     ptLogError(ptError_Argument,                           \
41                "Inserting an existing key (%s)",           \
42                Key.toLocal8Bit().data());                      \
43     assert (!m_Hash.contains(Key));                        \
44   }                                                        \
45   m_Hash[Key] = Item;
46 
47 ///////////////////////////////////////////////////////////////////////////////
48 //
49 // Constructor
50 //
51 ///////////////////////////////////////////////////////////////////////////////
52 
ptSettings(const short InitLevel,const QString Path)53 ptSettings::ptSettings(const short InitLevel, const QString Path) {
54 
55   assert(InitLevel<9); // 9 reserved for never to be remembered.
56 
57   // Load in the gui input elements
58   const ptGuiInputItem GuiInputItems[] = {
59     // Attention : Default,Min,Max,Step should be consistent int or double. Double *always* in X.Y notation to indicate so.
60     // Unique Name              uiElement,InitLevel,InJobFile,HasDefault  Default     Min       Max       Step    Decimals  Label,ToolTip
61     {"FileMgrThumbnailSize"          ,ptGT_InputSlider     ,1,0,1 ,100  ,50   ,500   ,25   ,0 ,tr("Thumbnail size")     ,tr("Thumbnail size in pixel")},
62     {"FileMgrThumbnailPadding"       ,ptGT_InputSlider     ,1,0,1 ,8    ,0    ,50    ,2    ,0 ,tr("Thumbnail padding")  ,tr("Thumbnail padding in pixel")},
63     {"FileMgrThumbMaxRowCol"         ,ptGT_Input           ,1,0,1 ,3    ,1    ,1000  ,1    ,0 ,tr("Thumbnails in a row/column") ,tr("Maximum number of thumbnails that should be placed in a row or column.")},
64     {"FileMgrThumbSaveSize"          ,ptGT_InputSlider     ,1,0,1 ,1000 ,50   ,8000  ,100  ,0 ,tr("Thumbnail export size")      ,tr("Thumbnail export size in pixel")},
65     {"FileMgrThumbCacheSize"         ,ptGT_InputSlider     ,1,0,1 ,250  ,0    ,2000  ,100  ,0 ,tr("Thumbnail cache (MB)")       ,tr("Maximum size of thumbnail cache in MBytes.\nRequires a restart to take effect.")},
66     {"MemoryTest"                    ,ptGT_InputSlider     ,9,0,1 ,0    ,0    ,500   ,50   ,0 ,tr("MB")                 ,tr("MB to waste")},
67     {"TabStatusIndicator"            ,ptGT_Input           ,1,0,1 ,8    ,0    ,16    ,1    ,0 ,tr("Pixel")              ,tr("Size of the LED")},
68     {"SliderWidth"                   ,ptGT_Input           ,1,0,1 ,0    ,0    ,500   ,50   ,0 ,tr("Maximum slider width") ,tr("Maximum slider width. Enter 0 to remove restriction")},
69     {"Zoom"                          ,ptGT_InputSlider     ,9,0,0 ,100  ,5    ,400   ,10   ,0 ,tr("Zoom")               ,tr("Zoom factor")},
70     {"ColorTemperature"              ,ptGT_InputSlider     ,2,1,1 ,6500 ,2000 ,15000 ,50   ,0 ,tr("Temp")               ,tr("Color Temperature")},
71     {"GreenIntensity"                ,ptGT_Input           ,2,1,1 ,1.0  ,0.001,5.0   ,0.01 ,3 ,tr("WB-G")               ,tr("Green Intensity in balance")},
72     {"RMultiplier"                   ,ptGT_Input           ,2,1,0 ,1.0  ,0.001,10.0  ,0.01 ,3 ,tr("R")                  ,tr("Red Multiplier in balance")},
73     {"GMultiplier"                   ,ptGT_Input           ,2,1,0 ,1.0  ,0.001,10.0  ,0.01 ,3 ,tr("G")                  ,tr("Green Multiplier in balance")},
74     {"BMultiplier"                   ,ptGT_Input           ,2,1,0 ,1.0  ,0.001,10.0  ,0.01 ,3 ,tr("B")                  ,tr("Blue Multiplier in balance")},
75     {"BlackPoint"                    ,ptGT_Input           ,2,1,0 ,0    ,0    ,0xffff,1    ,0 ,tr("BP")                 ,tr("Black point in raw")},
76     {"WhitePoint"                    ,ptGT_Input           ,2,1,0 ,0    ,0    ,0xffff,10   ,0 ,tr("WP")                 ,tr("White point in raw")},
77     {"CaRed"                         ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-5.0 ,5.0   ,0.5  ,2 ,tr("CA red factor")      ,tr("CA red factor")},
78     {"CaBlue"                        ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-5.0 ,5.0   ,0.5  ,2 ,tr("CA blue factor")     ,tr("CA blue factor")},
79     {"GreenEquil"                    ,ptGT_InputSlider     ,2,1,1 ,0    ,0    ,100   ,1    ,0 ,tr("Green equilibration"),tr("Green equilibration")},
80     {"CfaLineDenoise"                ,ptGT_InputSlider     ,2,1,1 ,0    ,0    ,50    ,1    ,0 ,tr("Line denoise")       ,tr("Raw line denoise threshold")},
81     {"AdjustMaximumThreshold"        ,ptGT_InputSlider     ,2,1,1 ,0.0  ,0.0  ,0.50  ,0.01 ,2 ,tr("Adjust maximum")     ,tr("Threshold to prevent pink highlights")},
82     {"RawDenoiseThreshold"           ,ptGT_InputSlider     ,2,1,1 ,0    ,0    ,2000  ,100  ,0 ,tr("Wavelet denoise")    ,tr("Raw wavelet denoise threshold")},
83     {"HotpixelReduction"             ,ptGT_InputSlider     ,2,1,1 ,0.0  ,0.0  ,1.0   ,0.05 ,3 ,tr("Badpixel reduction") ,tr("Automatic badpixel reduction")},
84     {"InterpolationPasses"           ,ptGT_Input           ,1,1,1 ,1    ,0    ,10    ,1    ,0 ,tr("Passes")             ,tr("Nr of refinement passes")},
85     {"MedianPasses"                  ,ptGT_Input           ,2,1,1 ,0    ,0    ,10     ,1    ,0 ,tr("Median passes")      ,tr("Nr of median filter passes")},
86     {"ESMedianPasses"                ,ptGT_Input           ,2,1,1 ,0    ,0    ,10     ,1    ,0 ,tr("Edge sensitive median passes")      ,tr("Nr of edge sensitive median filter passes")},
87     {"ClipParameter"                 ,ptGT_InputSlider     ,1,1,1 ,0    ,0    ,100   ,1    ,0 ,tr("Parameter")          ,tr("Clip function dependent parameter")},
88     {"LfunFocal"                     ,ptGT_Input           ,2,1,1 ,50.0 ,4.0  ,1000.0,1.0  ,0 ,tr("Focal length (35mm equiv.)"), tr("Focal length (35mm equiv.)")},
89     {"LfunAperture"                  ,ptGT_Input           ,2,1,1 ,8.0  ,0.8  ,32.0  ,1.0  ,1 ,tr("Aperture"), tr("")},
90     {"LfunDistance"                  ,ptGT_Input           ,2,1,1 ,1.0  ,0.01 ,500.0 ,1.0  ,2 ,tr("Distance"), tr("Distance between object and camera")},
91     {"LfunScale"                     ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.01  ,5.0   ,0.01 ,2 ,tr("Scale"),tr("Image scaling.\nUseful to avoid losing content through the distortion/geometry tools.\n0.0 means auto-scaling.")},
92     {"LfunCALinearKr"                ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.99 ,1.01  ,0.001,5 ,tr("kr"),tr("")},
93     {"LfunCALinearKb"                ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.99 ,1.01  ,0.001,5 ,tr("kb"),tr("")},
94     {"LfunCAPoly3Vr"                 ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.99 ,1.01  ,0.001,5 ,tr("vr"),tr("")},
95     {"LfunCAPoly3Vb"                 ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.99 ,1.01  ,0.001,5 ,tr("vb"),tr("")},
96     {"LfunCAPoly3Cr"                 ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.01,0.01  ,0.001,5 ,tr("cr"),tr("")},
97     {"LfunCAPoly3Cb"                 ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.01,0.01  ,0.001,5 ,tr("cb"),tr("")},
98     {"LfunCAPoly3Br"                 ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.01,0.01  ,0.001,5 ,tr("br"),tr("")},
99     {"LfunCAPoly3Bb"                 ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.01,0.01  ,0.001,5 ,tr("bb"),tr("")},
100     {"LfunVignettePoly6K1"           ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-1.0 ,2.0   ,0.01 ,3 ,tr("k1"),tr("")},
101     {"LfunVignettePoly6K2"           ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-1.0 ,2.0   ,0.01 ,3 ,tr("k2"),tr("")},
102     {"LfunVignettePoly6K3"           ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-1.0 ,2.0   ,0.01 ,3 ,tr("k3"),tr("")},
103     {"LfunDistPoly3K1"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("k1"),tr("")},
104     {"LfunDistPoly5K1"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("k1"),tr("")},
105     {"LfunDistPoly5K2"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("k2"),tr("")},
106 #if LF_VERSION < (3 << 16)
107     {"LfunDistFov1Omega"             ,ptGT_InputSlider     ,2,1,1 ,0.0  ,0.0  ,1.4   ,0.1  ,3 ,tr("omega"),tr("")},
108 #endif
109     {"LfunDistPTLensA"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("a"),tr("")},
110     {"LfunDistPTLensB"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("b"),tr("")},
111     {"LfunDistPTLensC"               ,ptGT_InputSlider     ,2,1,1 ,0.0  ,-0.2 ,0.2   ,0.01 ,4 ,tr("c"),tr("")},
112 
113     {"DefishFocalLength"             ,ptGT_Input           ,9,1,1 ,15.0 ,4.0  ,50.0  ,1.0  ,1 ,tr("Focal length (35mm equiv.)")  ,tr("Focal length (35mm equiv.)")},
114     {"DefishScale"                   ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.01  ,5.0   ,0.01 ,2 ,tr("Scale")              ,tr("Image scaling.\n0.0 means auto-scaling.")},
115     {"Rotate"                        ,ptGT_InputSlider     ,9,1,1 ,0.0  ,-180.0,180.0 ,0.1 ,2 ,tr("Rotate")             ,tr("Rotate")},
116     {"PerspectiveFocalLength"        ,ptGT_Input           ,9,1,1 ,50.0 ,4.0  ,600.0 ,1.0  ,0 ,tr("Focal length (35mm equiv.)")  ,tr("Focal length (35mm equiv.)")},
117     {"PerspectiveTilt"               ,ptGT_InputSlider     ,9,1,1 ,0.0  ,-45.0,45.0  ,0.1  ,2 ,tr("Tilt")               ,tr("Tilt")},
118     {"PerspectiveTurn"               ,ptGT_InputSlider     ,9,1,1 ,0.0  ,-45.0,45.0  ,0.1  ,2 ,tr("Turn")               ,tr("Turn")},
119     {"PerspectiveScaleX"             ,ptGT_InputSlider     ,9,1,1 ,1.0  ,0.2  ,5.0   ,0.05 ,2 ,tr("Horizontal scale")   ,tr("Horizontal scale")},
120     {"PerspectiveScaleY"             ,ptGT_InputSlider     ,9,1,1 ,1.0  ,0.2  ,5.0   ,0.05 ,2 ,tr("Vertical scale")     ,tr("Vertical scale")},
121     {"GridX"                         ,ptGT_Input           ,1,0,0 ,5    ,0    ,20    ,1    ,0 ,tr("X")                  ,tr("Vertical lines")},
122     {"GridY"                         ,ptGT_Input           ,1,0,0 ,5    ,0    ,20    ,1    ,0 ,tr("Y")                  ,tr("Horizontal lines")},
123     {"CropExposure"                  ,ptGT_InputSlider     ,1,1,1 ,0.0  ,-5.0 ,5.0   ,0.1  ,2 ,tr("Crop exposure")      ,tr("Temporary exposure in EV")},
124     {"LqrHorScale"                   ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.2  ,2.0   ,0.02 ,3 ,tr("Horizontal scale")   ,tr("Horizontal scale")},
125     {"LqrVertScale"                  ,ptGT_InputSlider     ,2,1,1 ,1.0  ,0.2  ,2.0   ,0.02 ,3 ,tr("Vertical scale")     ,tr("Vertical scale")},
126     {"LqrWidth"                      ,ptGT_Input           ,1,1,1 ,1200  ,200 ,6000  ,100  ,0 ,tr("Width")              ,tr("Width")},
127     {"LqrHeight"                     ,ptGT_Input           ,1,1,1 ,800   ,200 ,6000  ,100  ,0 ,tr("Height")             ,tr("Height")},
128     {"ResizeScale"                   ,ptGT_Input           ,1,1,1 ,1200  ,200 ,6000  ,100  ,0 ,tr("Pixels")             ,tr("Image size")},
129     {"ResizeHeight"                  ,ptGT_Input           ,1,1,1 ,800   ,200 ,6000  ,100  ,0 ,tr("Height")             ,tr("Image height")},
130     {"OutputGamma"                   ,ptGT_InputSlider     ,1,1,1 ,0.33  ,0.1  ,1.0   ,0.01 ,3 ,tr("Gamma")              ,tr("Gamma")},
131     {"OutputLinearity"               ,ptGT_InputSlider     ,1,1,1 ,0.06  ,0.0  ,1.0   ,0.01 ,3 ,tr("Linearity")          ,tr("Linearity")},
132     {"WebResizeScale"                ,ptGT_Input           ,1,1,1 ,1200  ,200 ,2600  ,100  ,0 ,tr("pixels")             ,tr("Image size")},
133     {"SaveQuality"                   ,ptGT_Input           ,1,1,1 ,97   ,25   ,100   ,1    ,0 ,tr("Quality")            ,tr("Quality")},
134     {"SaveResolution"                ,ptGT_Input           ,1,1,1 ,300  ,25   ,1200  ,100  ,0 ,tr("dpi")                ,tr("Resolution in dpi")},
135     {"ImageRating"                   ,ptGT_Input           ,2,1,1 ,0    ,0    ,5     ,1    ,0 ,tr("Rating")             ,tr("Image rating")}
136   };
137 
138   // Load in the gui choice (combo) elements
139   const ptGuiChoiceItem GuiChoiceItems[] = {
140     // Unique Name          GuiElement,InitLevel,InJobFile,HasDefault, Default            Choices (from ptGuiOptions.h),         ToolTip
141     {"BatchMgrAutosaveFile"        ,ptGT_Choice       ,1,0,0 ,bsfStandard                 ,GuiOptions->BatchMgrAutosaveFile      ,tr("File for autosaving batch list")},
142     {"RememberSettingLevel"        ,ptGT_Choice       ,1,0,0 ,2                           ,GuiOptions->RememberSettingLevel      ,tr("Remember setting level")},
143     {"CameraColor"                 ,ptGT_Choice       ,1,1,1 ,ptCameraColor_Adobe_Profile ,GuiOptions->CameraColor               ,tr("Transform camera RGB to working space RGB")},
144     {"CameraColorProfileIntent"    ,ptGT_Choice       ,1,1,1 ,INTENT_PERCEPTUAL           ,GuiOptions->CameraColorProfileIntent  ,tr("Intent of the profile")},
145     {"CameraColorGamma"            ,ptGT_Choice       ,1,1,1 ,ptCameraColorGamma_None     ,GuiOptions->CameraColorGamma          ,tr("Gamma that was applied before this profile")},
146     {"WorkColor"                   ,ptGT_Choice       ,1,1,1 ,ptSpace_sRGB_D65            ,GuiOptions->WorkColor                 ,tr("Working colorspace")},
147     {"CMQuality"                   ,ptGT_Choice       ,1,1,0 ,ptCMQuality_FastSRGB        ,GuiOptions->CMQuality                 ,tr("Color management quality")},
148     {"PreviewColorProfileIntent"   ,ptGT_Choice       ,1,0,1 ,INTENT_PERCEPTUAL           ,GuiOptions->PreviewColorProfileIntent ,tr("Intent of the profile")},
149     {"OutputColorProfileIntent"    ,ptGT_Choice       ,1,1,1 ,INTENT_PERCEPTUAL           ,GuiOptions->OutputColorProfileIntent  ,tr("Intent of the profile")},
150     {"SaveButtonMode"              ,ptGT_Choice       ,1,0,1 ,ptOutputMode_Pipe           ,GuiOptions->OutputMode                ,tr("Output mode of save button")},
151     {"ResetButtonMode"             ,ptGT_Choice       ,1,0,1 ,ptResetMode_User            ,GuiOptions->ResetMode                 ,tr("Output mode of reset button")},
152     {"Style"                       ,ptGT_Choice       ,1,0,0 ,ptStyle_DarkGrey            ,GuiOptions->Style                     ,tr("Set the theme.")},
153     {"StyleHighLight"              ,ptGT_Choice       ,1,0,0 ,ptStyleHighLight_Green      ,GuiOptions->StyleHighLight            ,tr("Set the highlight color of the theme.")},
154     {"StartupUIMode"               ,ptGT_Choice       ,1,0,0 ,ptStartupUIMode_Tab         ,GuiOptions->StartupUIMode             ,tr("Set the start up mode for the UI.")},
155     {"PipeSize"                    ,ptGT_Choice       ,2,0,1 ,ptPipeSize_Quarter          ,GuiOptions->PipeSize                  ,tr("Size of image processed vs original.")},
156     {"StartupPipeSize"             ,ptGT_Choice       ,1,0,1 ,ptPipeSize_Quarter          ,GuiOptions->PipeSize                  ,tr("Initial pipe size when Photivo starts.")},
157     {"SpecialPreview"              ,ptGT_Choice       ,2,0,1 ,ptSpecialPreview_RGB        ,GuiOptions->SpecialPreview            ,tr("Special preview for image analysis")},
158     {"BadPixels"                   ,ptGT_Choice       ,1,1,0 ,0                           ,GuiOptions->BadPixels                 ,tr("Bad pixels file")},
159     {"DarkFrame"                   ,ptGT_Choice       ,1,1,0 ,0                           ,GuiOptions->DarkFrame                 ,tr("Darkframe file")},
160     {"WhiteBalance"                ,ptGT_Choice       ,2,1,1 ,ptWhiteBalance_Camera       ,GuiOptions->WhiteBalance              ,tr("WhiteBalance")},
161     {"CaCorrect"                   ,ptGT_Choice       ,2,1,1 ,ptCACorrect_Off             ,GuiOptions->CACorrect                 ,tr("CA correction")},
162     {"Interpolation"               ,ptGT_Choice       ,2,1,1 ,ptInterpolation_DCB         ,GuiOptions->Interpolation             ,tr("Demosaicing algorithm")},
163     {"BayerDenoise"                ,ptGT_Choice       ,2,1,1 ,ptBayerDenoise_None         ,GuiOptions->BayerDenoise              ,tr("Denosie on Bayer pattern")},
164 
165     {"CropGuidelines"              ,ptGT_Choice       ,1,0,0 ,ptGuidelines_GoldenRatio    ,GuiOptions->CropGuidelines            ,tr("Guide lines for crop")},
166     {"LightsOut"                   ,ptGT_Choice       ,1,0,0 ,ptLightsOutMode_Dimmed      ,GuiOptions->LightsOutMode             ,tr("Dim areas outside the crop rectangle")},
167     {"ClipMode"                    ,ptGT_Choice       ,1,1,1 ,ptClipMode_Blend            ,GuiOptions->ClipMode                  ,tr("How to handle clipping")},
168     {"LfunCAModel"                 ,ptGT_Choice       ,2,1,1 ,ptLfunCAModel_None          ,GuiOptions->LfunCAModel               ,tr("Mathematical model for CA correction")},
169     {"LfunVignetteModel"           ,ptGT_Choice       ,2,1,1 ,ptLfunVignetteModel_None    ,GuiOptions->LfunVignetteModel         ,tr("Mathematical model for vignetting correction")},
170     {"LfunSrcGeo"                  ,ptGT_Choice       ,2,1,1 ,ptLfunGeo_Unknown           ,GuiOptions->LfunGeo                   ,tr("Geometry of the lens the image was taken with")},
171     {"LfunTargetGeo"               ,ptGT_Choice       ,2,1,1 ,ptLfunGeo_Unknown           ,GuiOptions->LfunGeo                   ,tr("Convert image to this lens geometry")},
172     {"LfunDistModel"               ,ptGT_Choice       ,2,1,1 ,ptLfunDistModel_None        ,GuiOptions->LfunDistModel             ,tr("Mathematical distortion model to apply to the image")},
173     {"LqrEnergy"                   ,ptGT_Choice       ,2,1,1 ,ptLqr_Disabled              ,GuiOptions->LqrEnergy                 ,tr("Energy method for liquid rescale")},
174     {"LqrScaling"                  ,ptGT_Choice       ,1,1,1 ,ptLqr_ScaleRelative         ,GuiOptions->LqrScaling                ,tr("Scaling method for liquid rescale")},
175     {"ResizeFilter"                ,ptGT_Choice       ,1,1,1 ,ptIMFilter_Mitchell         ,GuiOptions->IMResizeFilter            ,tr("Filter to be used for resizing")},
176     {"ResizeDimension"             ,ptGT_Choice       ,2,1,1 ,ptResizeDimension_LongerEdge,GuiOptions->ResizeDimension           ,tr("Image dimension the resize value applies to")},
177     {"FlipMode"                    ,ptGT_Choice       ,2,1,1 ,ptFlipMode_None             ,GuiOptions->FlipMode                  ,tr("Flip mode")},
178     {"AspectRatioW"                ,ptGT_Choice       ,2,0,0 ,3                           ,GuiOptions->AspectRatio               ,tr("Aspect width")},
179     {"AspectRatioH"                ,ptGT_Choice       ,2,0,0 ,2                           ,GuiOptions->AspectRatio               ,tr("Aspect height")},
180     {"WebResize"                   ,ptGT_Choice       ,2,1,1 ,ptEnable_None               ,GuiOptions->Enable                    ,tr("Enable web resizing")},
181     {"WebResizeDimension"          ,ptGT_Choice       ,2,1,1 ,ptResizeDimension_LongerEdge,GuiOptions->WebResizeDimension        ,tr("Image dimension the resize value applies to")},
182     {"WebResizeFilter"             ,ptGT_Choice       ,1,1,1 ,ptIMFilter_Lanczos          ,GuiOptions->IMResizeFilter            ,tr("Filter to be used for resizing")},
183     {"SaveFormat"                  ,ptGT_Choice       ,1,1,1 ,ptSaveFormat_JPEG           ,GuiOptions->SaveFormat                ,tr("Output format")},
184     {"SaveSampling"                ,ptGT_Choice       ,1,1,1 ,ptSaveSampling_211          ,GuiOptions->SaveSampling              ,tr("JPEG color sampling")},
185     {"CropInitialZoom"             ,ptGT_Choice       ,1,0,1 ,ptZoomLevel_Fit             ,GuiOptions->ZoomLevel                 ,tr("Switch to this zoom level when starting to crop.")}
186   };
187 
188   // Load in the gui check elements
189   const ptGuiCheckItem GuiCheckItems[] = {
190     // Name   GuiType,InitLevel,InJobFile,Default,Label,Tip
191     {"FileMgrUseThumbMaxRowCol"   ,ptGT_Check ,1,0,0,tr("At most")         ,tr("Maximum number of thumbnails that should be placed in a row or column.")},
192     {"FileMgrStartupOpen"         ,ptGT_Check ,1,0,0,tr("Open file manager on startup"), tr("Opens the file manager when Photivo starts without an image")},
193 
194     {"BatchMgrAutosave"           ,ptGT_Check ,1,0,1,tr("Automatically save batch list"), tr("Automatically save current batch list")},
195     {"BatchMgrAutoload"           ,ptGT_Check ,1,0,0,tr("Automatically load batch list"), tr("Automatically load previous batch list saved to standard path on startup")},
196 
197     {"StartupSettings"            ,ptGT_Check ,1,0,1,tr("User settings")   ,tr("Load user settings on startup")},
198     {"StartupSettingsReset"       ,ptGT_Check ,1,0,0,tr("Reset on new image") ,tr("Reset to user settings when new image is opened")},
199     {"StartupSwitchAR"            ,ptGT_Check ,1,0,1,tr("Adjust aspect ratio") ,tr("Adjust crop aspect ratio to image aspect ratio")},
200     {"InputsAddPowerLaw"          ,ptGT_Check ,1,1,1,tr("Nonlinear slider response")   ,tr("Alter the slider behaviour")},
201     {"ExportToGimp"               ,ptGT_Check ,1,0,1,tr("Use gimp plugin") ,tr("Use gimp plugin for export")},
202     {"ToolBoxMode"                ,ptGT_Check ,1,0,0,tr("Enabled")         ,tr("Show seperate toolboxes")},
203     {"PreviewTabMode"             ,ptGT_Check ,1,0,0,tr("Tab mode")        ,tr("Show the preview after the active tab")},
204     {"BackgroundColor"            ,ptGT_Check ,1,0,0,tr("Override default"),tr("Override the default color")},
205     {"SearchBarEnable"            ,ptGT_Check ,1,0,1,tr("Display search bar"),tr("Display search bar")},
206     {"WriteBackupSettings"        ,ptGT_Check ,1,0,0,tr("Backup settings") ,tr("Write backup settings during processing")},
207     {"RunMode"                    ,ptGT_Check ,1,0,0,tr("manual")          ,tr("manual or automatic pipe")},
208     {"UseThumbnail"               ,ptGT_Check ,1,1,0,tr("Use thumbnail")   ,tr("Use the embedded thumbnail of RAW images")},
209     {"MultiplierEnhance"          ,ptGT_Check ,1,1,0,tr("Intensify")       ,tr("Normalize lowest channel to 1")},
210     {"ManualBlackPoint"           ,ptGT_Check ,2,1,0,tr("Manual BP")       ,tr("Manual black point setting enabled")},
211     {"ManualWhitePoint"           ,ptGT_Check ,2,1,0,tr("Manual WP")       ,tr("Manual white point setting enabled")},
212     {"EeciRefine"                 ,ptGT_Check ,2,1,0,tr("Eeci refinement") ,tr("Eeci refinement")},
213     {"LfunAutoScale"              ,ptGT_Check ,2,1,0,tr("Auto scale")      ,tr("Auto scale to avoid black borders after distortion correction or geometry conversion.")},
214     {"Defish"                     ,ptGT_Check ,2,1,0,tr("Enable")          ,tr("Enable defishing")},
215     {"DefishAutoScale"            ,ptGT_Check ,2,1,0,tr("Auto scale")      ,tr("Auto scale to avoid black borders")},
216     {"Grid"                       ,ptGT_Check ,9,1,0,tr("Grid")            ,tr("Enable the overlay grid")},
217     {"Crop"                       ,ptGT_Check ,9,1,0,tr("Crop")            ,tr("Enable to make a crop")},
218     {"FixedAspectRatio"           ,ptGT_Check ,1,0,0,tr("Aspect Ratio")    ,tr("Crop with a fixed aspect ratio")},
219     {"LqrVertFirst"               ,ptGT_Check ,2,1,0,tr("Vertical first")  ,tr("Resizing starts with vertical direction")},
220     {"Resize"                     ,ptGT_Check ,9,1,0,tr("Resize")          ,tr("Enable resize")},
221     {"AutomaticPipeSize"          ,ptGT_Check ,1,1,0,tr("Automatic pipe size") ,tr("Automatic pipe size")},
222     {"GeometryBlock"              ,ptGT_Check ,9,0,0,tr("Block pipe")      ,tr("Disable the pipe")},
223     {"WebResizeBeforeGamma"       ,ptGT_Check ,1,1,0,tr("before gamma")    ,tr("Webresizing before gamma compensation")},
224     {"OutputGammaCompensation"    ,ptGT_Check ,1,1,0,tr("sRGB gamma compensation")    ,tr("sRGB gamma compensation")},
225     {"IncludeExif"                ,ptGT_Check ,2,1,1,tr("Include metadata"),tr("Include metadata (only in jpeg and tiff)")},
226     {"EraseExifThumbnail"         ,ptGT_Check ,2,1,1,tr("Erase thumbnail") ,tr("Erase the exif thumbnail (only in jpeg and tiff)")},
227     {"SaveConfirmation"           ,ptGT_Check ,1,0,1,tr("Save image")      ,tr("Confirm any action that would discard an unsaved image")},
228     {"AutosaveSettings"           ,ptGT_Check ,1,0,1,tr("Autosave settings"),tr("Autosave settings when loading another image (if save confirmation is off)")},
229     {"ResetSettingsConfirmation"  ,ptGT_Check, 1,0,1,tr("Reset settings")  ,tr("Confirm resetting settings or dropping a settings file onto an image")},
230     {"FullPipeConfirmation"       ,ptGT_Check ,1,0,1,tr("Switch to 1:1 pipe"), tr("Confirm switch to the full sized pipe")},
231     {"EscToExit"                  ,ptGT_Check ,1,0,0,tr("Esc key exits Photivo"),tr("Use the Esc key not only to exit special view modes (e.g. full screen) but also to close Photivo.")},
232     {"LoadTags"                   ,ptGT_Check ,1,0,0,tr("Load tags from sidecar files"),tr("Load tags from sidecar XMP files when opening an image.")}
233   };
234 
235   // Load in the non gui elements
236   const ptItem Items[] = {
237     // Name                             InitLevel  Default                               JobFile
238     {"PipeIsRunning"                        ,9    ,0                                     ,0},
239     {"BlockTools"                           ,9    ,0                                     ,0},
240     {"InputPowerFactor"                     ,0    ,2.2                                   ,1},
241     {"PreviewMode"                          ,1    ,ptPreviewMode_End                     ,0},
242     {"ZoomMode"                             ,9    ,ptZoomMode_Fit                        ,0},
243     {"Scaled"                               ,9    ,0                                     ,0},
244     {"IsRAW"                                ,9    ,1                                     ,0},
245     {"HaveImage"                            ,9    ,0                                     ,0},
246     {"RawsDirectory"                        ,0    ,""                                    ,0},
247     {"OutputDirectory"                      ,0    ,""                                    ,1},
248     {"MainDirectory"                        ,0    ,"@INSTALL@/"                          ,0},
249     {"ShareDirectory"                       ,0    ,"@INSTALL@/"                          ,1},
250     {"UserDirectory"                        ,0    ,"@INSTALL@/"                          ,1},
251     {"UIDirectory"                          ,0    ,"@INSTALL@/UISettings"                ,0},
252     {"TranslationsDirectory"                ,0    ,"@INSTALL@/Translations"              ,0},
253     {"CurvesDirectory"                      ,0    ,"@INSTALL@/Curves"                    ,1},
254     {"ChannelMixersDirectory"               ,0    ,"@INSTALL@/ChannelMixers"             ,1},
255     {"PresetDirectory"                      ,0    ,"@INSTALL@/Presets"                   ,0},
256     {"CameraColorProfilesDirectory"         ,0    ,"@INSTALL@/Profiles/Camera"           ,1},
257     {"PreviewColorProfilesDirectory"        ,0    ,"@INSTALL@/Profiles/Preview"          ,0},
258     {"OutputColorProfilesDirectory"         ,0    ,"@INSTALL@/Profiles/Output"           ,1},
259     {"StandardAdobeProfilesDirectory"       ,0    ,"@INSTALL@/Profiles/Camera/Standard"  ,1},
260     {"LensfunDatabaseDirectory"             ,0    ,"@INSTALL@/LensfunDatabase"           ,1},
261     {"PreviewColorProfile"                  ,1    ,"@INSTALL@/Profiles/Preview/sRGB.icc" ,1},
262     {"OutputColorProfile"                   ,1    ,"@INSTALL@/Profiles/Output/sRGB.icc"  ,1},
263     {"GimpExecCommand"                      ,1    ,"gimp"                                ,0},
264     {"StartupSettingsFile"                  ,1    ,"@INSTALL@/Presets/MakeFancy.pts"     ,0},
265     {"CameraMake"                           ,9    ,""                                    ,0},
266     {"CameraModel"                          ,9    ,""                                    ,0},
267     {"CameraColorProfile"                   ,1    ,""                                    ,1},
268     {"HaveBadPixels"                        ,1    ,0                                     ,1},
269     {"BadPixelsFileName"                    ,1    ,""                                    ,1},
270     {"HaveDarkFrame"                        ,1    ,0                                     ,1},
271     {"DarkFrameFileName"                    ,1    ,""                                    ,1},
272     {"Sidecar"                              ,1    ,""                                    ,1},
273     {"VisualSelectionX"                     ,9    ,0                                     ,1},
274     {"VisualSelectionY"                     ,9    ,0                                     ,1},
275     {"VisualSelectionWidth"                 ,9    ,0                                     ,1},
276     {"VisualSelectionHeight"                ,9    ,0                                     ,1},
277     {"ImageW"                               ,9    ,0                                     ,0},
278     {"ImageH"                               ,9    ,0                                     ,0},
279     {"PipeImageW"                           ,9    ,0                                     ,0},
280     {"PipeImageH"                           ,9    ,0                                     ,0},
281     {"CropX"                                ,9    ,0                                     ,1},
282     {"CropY"                                ,9    ,0                                     ,1},
283     {"CropW"                                ,9    ,0                                     ,1},
284     {"CropH"                                ,9    ,0                                     ,1},
285     {"RotateW"                              ,9    ,0                                     ,1},
286     {"RotateH"                              ,9    ,0                                     ,1},
287     {"ExposureNormalization"                ,9    ,0.0                                   ,0},
288     {"CurveFileNamesRGB"                    ,0    ,QStringList()                         ,1},
289     {"CurveFileNamesR"                      ,0    ,QStringList()                         ,1},
290     {"CurveFileNamesG"                      ,0    ,QStringList()                         ,1},
291     {"CurveFileNamesB"                      ,0    ,QStringList()                         ,1},
292     {"CurveFileNamesL"                      ,0    ,QStringList()                         ,1},
293     {"CurveFileNamesLa"                     ,0    ,QStringList()                         ,1},
294     {"CurveFileNamesLb"                     ,0    ,QStringList()                         ,1},
295     {"CurveFileNamesOutline"                ,0    ,QStringList()                         ,1},
296     {"CurveFileNamesLByHue"                 ,0    ,QStringList()                         ,1},
297     {"CurveFileNamesHue"                    ,0    ,QStringList()                         ,1},
298     {"CurveFileNamesTexture"                ,0    ,QStringList()                         ,1},
299     {"CurveFileNamesSaturation"             ,0    ,QStringList()                         ,1},
300     {"CurveFileNamesBase"                   ,0    ,QStringList()                         ,1},
301     {"CurveFileNamesBase2"                  ,0    ,QStringList()                         ,1},
302     {"CurveFileNamesShadowsHighlights"      ,0    ,QStringList()                         ,1},
303     {"CurveFileNamesDenoise"                ,0    ,QStringList()                         ,1},
304     {"CurveFileNamesDenoise2"               ,0    ,QStringList()                         ,1},
305     {"OutputFileName"                       ,9    ,""                                    ,0}, // Not in JobFile. Constructed.
306     {"JobMode"                              ,9    ,0                                     ,0}, // Not in JobFile !! Overwrites else.
307     {"InputFileNameList"                    ,9    ,QStringList()                         ,1},
308     {"DigikamTagsList"                      ,9    ,QStringList()                         ,1},
309     {"TagsList"                             ,9    ,QStringList()                         ,1},
310     {"OutputFileNameSuffix"                 ,9    ,""                                    ,1},
311     {"ImageTitle"                           ,9    ,""                                    ,1},
312     {"Copyright"                            ,1    ,""                                    ,1},
313     {"BackgroundRed"                        ,1    ,0                                     ,0},
314     {"BackgroundGreen"                      ,1    ,0                                     ,0},
315     {"BackgroundBlue"                       ,1    ,0                                     ,0},
316     {"HistogramChannel"                     ,1    ,ptHistogramChannel_RGB                ,0},
317     {"HistogramLogX"                        ,1    ,0                                     ,0},
318     {"HistogramLogY"                        ,1    ,1                                     ,0},
319     {"HistogramMode"                        ,1    ,ptHistogramMode_Preview               ,0},
320     {"HistogramCrop"                        ,9    ,0                                     ,0},
321     {"HistogramCropX"                       ,9    ,0                                     ,0},
322     {"HistogramCropY"                       ,9    ,0                                     ,0},
323     {"HistogramCropW"                       ,9    ,0                                     ,0},
324     {"HistogramCropH"                       ,9    ,0                                     ,0},
325     {"PixelReader"                          ,1    ,0                                     ,0},
326     {"ExposureIndicator"                    ,1    ,0                                     ,0},
327     {"ExposureIndicatorSensor"              ,0    ,0                                     ,0},
328     {"ExposureIndicatorR"                   ,0    ,1                                     ,0},
329     {"ExposureIndicatorG"                   ,0    ,1                                     ,0},
330     {"ExposureIndicatorB"                   ,0    ,1                                     ,0},
331     {"ExposureIndicatorOver"                ,0    ,1                                     ,0},
332     {"ExposureIndicatorUnder"               ,0    ,1                                     ,0},
333     {"ShowExposureIndicatorSensor"          ,0    ,0                                     ,0},
334     {"ShowBottomContainer"                  ,1    ,1                                     ,0},
335     {"ShowToolContainer"                    ,9    ,1                                     ,0},
336     {"SatCurveType"                         ,1    ,0                                     ,1},
337     {"TextureCurveType"                     ,1    ,0                                     ,1},
338     {"DenoiseCurveType"                     ,1    ,0                                     ,1},
339     {"Denoise2CurveType"                    ,1    ,0                                     ,1},
340     {"HueCurveType"                         ,1    ,0                                     ,1},
341     {"FullOutput"                           ,9    ,0                                     ,0},
342     {"HiddenTools"                          ,0    ,QStringList(Fuid::LumaDenoiseCurve2_LabSN)
343                                                                                          ,1},
344     {"FavouriteTools"                       ,0    ,QStringList()                         ,0},
345     {"BlockedTools"                         ,0    ,QStringList()                         ,1},
346     {"DisabledTools"                        ,9    ,QStringList()                         ,0},
347     {"BlockUpdate"                          ,9    ,0                                     ,0},
348     {"FocalLengthIn35mmFilm"                ,0    ,0.0                                   ,0},
349     {"ApertureFromExif"                     ,0    ,0.0                                   ,0},   // aperture from exif data
350     {"DetailViewActive"                     ,9    ,0                                     ,0},
351     {"DetailViewScale"                      ,9    ,0                                     ,0},
352     {"DetailViewCropX"                      ,9    ,0                                     ,0},
353     {"DetailViewCropY"                      ,9    ,0                                     ,0},
354     {"DetailViewCropW"                      ,9    ,0                                     ,0},
355     {"DetailViewCropH"                      ,9    ,0                                     ,0},
356     {"TranslationMode"                      ,1    ,0                                     ,0},  // 0 no transl (English), 1 load qm file
357     {"UiLanguage"                           ,1    ,""                                    ,0},  // Language name to load from qm file, e.g. "Deutsch"
358     {"CustomCSSFile"                        ,1    ,""                                    ,0},
359     {"FullscreenActive"                     ,9    ,0                                     ,0},
360 
361     // stuff for the file manager
362     {"PreventFileMgrStartup"                ,9    ,0                                     ,0},
363     {"FileMgrIsOpen"                        ,9    ,0                                     ,0},
364     {"LastFileMgrLocation"                  ,1    ,""                                    ,0},
365     {"FileMgrShowDirThumbs"                 ,1    ,1                                     ,0},
366     {"FileMgrShowImageView"                 ,1    ,1                                     ,0},
367     {"FileMgrShowSidebar"                   ,1    ,1                                     ,0},
368     {"FileMgrThumbLayoutType"               ,1    ,tlVerticalByRow                       ,0},
369     {"FileMgrShowRAWs"                      ,1    ,1                                     ,0},
370     {"FileMgrShowBitmaps"                   ,1    ,1                                     ,0},
371     {"BatchIsOpen"                          ,9    ,0                                     ,0},
372     {"BatchLogIsVisible"                    ,1    ,0                                     ,0}
373   };
374 
375    // Gui Numerical inputs. Copy them from the const array in ptSettingItem.
376   short NrSettings = sizeof(GuiInputItems)/sizeof(ptGuiInputItem);
377   for (short i=0; i<NrSettings; i++) {
378     ptGuiInputItem Description = GuiInputItems[i];
379     ptSettingItem* SettingItem = new ptSettingItem;
380     SettingItem->GuiType         = Description.GuiType;
381     SettingItem->InitLevel       = Description.InitLevel;
382     SettingItem->InJobFile       = Description.InJobFile;
383     SettingItem->HasDefaultValue = Description.HasDefaultValue;
384     SettingItem->DefaultValue    = Description.DefaultValue;
385     SettingItem->MinimumValue    = Description.MinimumValue;
386     SettingItem->MaximumValue    = Description.MaximumValue;
387     SettingItem->Step            = Description.Step;
388     SettingItem->NrDecimals      = Description.NrDecimals;
389     SettingItem->Label           = Description.Label;
390     SettingItem->ToolTip         = Description.ToolTip;
391     M_InsertKeyIntoHash(Description.KeyName,SettingItem);
392   }
393   // Gui Choice inputs. Copy them from the const array in ptSettingItem.
394   NrSettings = sizeof(GuiChoiceItems)/sizeof(ptGuiChoiceItem);
395   for (short i=0; i<NrSettings; i++) {
396     ptGuiChoiceItem Description = GuiChoiceItems[i];
397     ptSettingItem* SettingItem = new ptSettingItem;
398     SettingItem->GuiType         = Description.GuiType;
399     SettingItem->InitLevel       = Description.InitLevel;
400     SettingItem->InJobFile       = Description.InJobFile;
401     SettingItem->HasDefaultValue = Description.HasDefaultValue;
402     SettingItem->DefaultValue    = Description.DefaultValue;
403     SettingItem->Value           = Description.DefaultValue;
404     SettingItem->ToolTip         = Description.ToolTip;
405     SettingItem->InitialOptions  = Description.InitialOptions;
406     M_InsertKeyIntoHash(Description.KeyName,SettingItem);
407   }
408   // Gui Check inputs. Copy them from the const array in ptSettingItem.
409   NrSettings = sizeof(GuiCheckItems)/sizeof(ptGuiCheckItem);
410   for (short i=0; i<NrSettings; i++) {
411     ptGuiCheckItem Description = GuiCheckItems[i];
412     ptSettingItem* SettingItem = new ptSettingItem;
413     SettingItem->GuiType      = Description.GuiType;
414     SettingItem->InitLevel    = Description.InitLevel;
415     SettingItem->InJobFile    = Description.InJobFile;
416     SettingItem->DefaultValue = Description.DefaultValue;
417     SettingItem->Value        = Description.DefaultValue;
418     SettingItem->Label        = Description.Label;
419     SettingItem->ToolTip      = Description.ToolTip;
420     M_InsertKeyIntoHash(Description.KeyName,SettingItem);
421   }
422   // Non gui elements
423   NrSettings = sizeof(Items)/sizeof(ptItem);
424   for (short i=0; i<NrSettings; i++) {
425     ptItem Description = Items[i];
426     ptSettingItem* SettingItem = new ptSettingItem;
427     SettingItem->GuiType      = ptGT_None;
428     SettingItem->InitLevel    = Description.InitLevel;
429     if (Description.DefaultValue.type() == QVariant::String) {
430       QString Tmp = Description.DefaultValue.toString();
431       Tmp.replace(QString("@INSTALL@"),QCoreApplication::applicationDirPath());
432       Description.DefaultValue = Tmp;
433     }
434     SettingItem->DefaultValue = Description.DefaultValue;
435     SettingItem->Value        = Description.DefaultValue;
436     SettingItem->InJobFile    = Description.InJobFile;
437     M_InsertKeyIntoHash(Description.KeyName,SettingItem);
438   }
439 
440   // Now we have initialized from static values.
441   // In the second round we overwrite now with what's coming from the ini
442   // files.
443 
444   // Persistent settings.
445   m_IniSettings = new QSettings(Path + "photivo.ini", QSettings::IniFormat);
446 
447   QStringList Keys = m_Hash.keys();
448   for (int i=0; i<Keys.size(); i++) {
449     QString Key = Keys[i];
450     ptSettingItem* Setting = m_Hash[Key];
451 
452     if (InitLevel > Setting->InitLevel) {
453       // Default needs to be overwritten by something coming from ini file.
454       Setting->Value = m_IniSettings->value(Key,Setting->DefaultValue);
455       // Correction needed as the values coming from the ini file are
456       // often interpreted as strings even if they could be int or so.
457       const QVariant::Type TargetType = Setting->DefaultValue.type();
458       if (Setting->Value.type() != TargetType) {
459         if (TargetType == QVariant::Int ||
460           TargetType == QVariant::UInt) {
461           Setting->Value = Setting->Value.toInt();
462         } else if (TargetType == QVariant::Double ||
463                    (QMetaType::Type) TargetType == QMetaType::Float) {
464           Setting->Value = Setting->Value.toDouble();
465         } else if (TargetType == QVariant::StringList) {
466           Setting->Value = Setting->Value.toStringList();
467         } else {
468           ptLogError(ptError_Argument,"Unexpected type %d",TargetType);
469           assert(0);
470         }
471       }
472       // Seen above this shouldn't happen, but better safe then sorry.
473       if (Setting->Value.type() != Setting->DefaultValue.type()) {
474         ptLogError(ptError_Argument,
475                    "Type conversion error from ini file. Should : %d Is : %d\n",
476                    Setting->DefaultValue.type(),Setting->Value.type());
477         assert(Setting->Value.type() == Setting->DefaultValue.type());
478       }
479     } else {
480       Setting->Value = Setting->DefaultValue;
481     }
482   }
483 
484   // Some ad-hoc corrections
485   QFileInfo PathInfo(GetValue("PreviewColorProfile").toString());
486   SetValue("PreviewColorProfile",PathInfo.absoluteFilePath());
487   PathInfo.setFile(GetValue("PreviewColorProfile").toString());
488   SetValue("PreviewColorProfile",PathInfo.absoluteFilePath());
489   SetValue("Scaled",GetValue("PipeSize"));
490 };
491 
492 ////////////////////////////////////////////////////////////////////////////////
493 //
494 // Destructor
495 // Basically dumping the whole Settings hash to ini files.
496 //
497 ////////////////////////////////////////////////////////////////////////////////
498 
~ptSettings()499 ptSettings::~ptSettings() {
500   QStringList Keys = m_Hash.keys();
501   for (int i=0; i<Keys.size(); i++) {
502     QString Key = Keys[i];
503     ptSettingItem* Setting = m_Hash[Key];
504     m_IniSettings->setValue(Key,Setting->Value);
505   }
506   // Explicit call destructor (such that synced to disk)
507   delete m_IniSettings;
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////
511 //
512 // GetValue
513 // Access to the hash, but with protection on non existing key.
514 //
515 ////////////////////////////////////////////////////////////////////////////////
516 
GetValue(const QString Key) const517 const QVariant ptSettings::GetValue(const QString Key) const {
518   if (!m_Hash.contains(Key)) {
519     ptLogError(ptError_Argument,
520                "(%s,%d) Could not find key '%s'\n",
521                __FILE__,__LINE__,Key.toLocal8Bit().data());
522     assert (m_Hash.contains(Key));
523   }
524   return m_Hash[Key]->Value;
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 //
529 // GetInt
530 //
531 ////////////////////////////////////////////////////////////////////////////////
532 
GetInt(const QString Key) const533 int ptSettings::GetInt(const QString Key) const {
534   // Remark : UInt and Int are mixed here.
535   // The only settings related type where u is important is uint16_t
536   // (dimensions). uint16_t fits in an integer which is 32 bit.
537   QVariant Tmp = GetValue(Key);
538   if (Tmp.type() != QVariant::Int && Tmp.type() != QVariant::UInt) {
539     ptLogError(ptError_Argument,
540                "Expected 'QVariant::(U)Int' but got '%d' for key '%s'\n",
541                Tmp.type(),Key.toLocal8Bit().data());
542     if (Tmp.type() == QVariant::String) {
543       ptLogError(ptError_Argument,
544                  "Additionally : it's a string '%s'\n",
545                  Tmp.toString().toLocal8Bit().data());
546     }
547     assert(Tmp.type() == QVariant::Int);
548   }
549   return Tmp.toInt();
550 }
551 
552 ////////////////////////////////////////////////////////////////////////////////
553 //
554 // GetDouble
555 //
556 ////////////////////////////////////////////////////////////////////////////////
557 
GetDouble(const QString Key) const558 double ptSettings::GetDouble(const QString Key) const {
559   QVariant Tmp = GetValue(Key);
560   if (static_cast<QMetaType::Type>(Tmp.type()) == QMetaType::Float)
561     Tmp.convert(QVariant::Double);
562   if (Tmp.type() != QVariant::Double) {
563     ptLogError(ptError_Argument,
564                "Expected 'QVariant::Double' but got '%d' for key '%s'\n",
565                Tmp.type(),Key.toLocal8Bit().data());
566     assert(Tmp.type() == QVariant::Double);
567   }
568   return Tmp.toDouble();
569 }
570 
571 ////////////////////////////////////////////////////////////////////////////////
572 //
573 // GetString
574 //
575 ////////////////////////////////////////////////////////////////////////////////
576 
GetString(const QString Key) const577 const QString ptSettings::GetString(const QString Key) const {
578   QVariant Tmp = GetValue(Key);
579   if (Tmp.type() != QVariant::String) {
580     ptLogError(ptError_Argument,
581                "Expected 'QVariant::String' but got '%d' for key '%s'\n",
582                Tmp.type(),Key.toLocal8Bit().data());
583     assert(Tmp.type() == QVariant::String);
584   }
585   return Tmp.toString();
586 }
587 
588 ////////////////////////////////////////////////////////////////////////////////
589 //
590 // GetStringList
591 //
592 ////////////////////////////////////////////////////////////////////////////////
593 
GetStringList(const QString Key) const594 const QStringList ptSettings::GetStringList(const QString Key) const {
595   QVariant Tmp = GetValue(Key);
596   if (Tmp.type() != QVariant::StringList) {
597     ptLogError(ptError_Argument,
598                "Expected 'QVariant::StringList' but got '%d' for key '%s'\n",
599                Tmp.type(),Key.toLocal8Bit().data());
600     assert(Tmp.type() == QVariant::StringList);
601   }
602   return Tmp.toStringList();
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 //
607 // SetValue
608 // Access to the hash, but with protection on non existing key.
609 //
610 ////////////////////////////////////////////////////////////////////////////////
611 
SetValue(const QString Key,const QVariant Value)612 void ptSettings::SetValue(const QString Key, const QVariant Value) {
613   if (!m_Hash.contains(Key)) {
614     ptLogError(ptError_Argument,
615                "(%s,%d) Could not find key '%s'\n",
616                __FILE__,__LINE__,Key.toLocal8Bit().data());
617     assert (m_Hash.contains(Key));
618   }
619   m_Hash[Key]->Value = Value;
620   // In job mode there are no gui elements and we have to return.
621   if (GetInt("JobMode")) return;
622   // If it's a gui element, we have to update it at once for consistency.
623   switch (m_Hash[Key]->GuiType) {
624     case ptGT_Input :
625     case ptGT_InputSlider :
626     case ptGT_InputSliderHue :
627       m_Hash[Key]->GuiInput->SetValue(Value);
628       break;
629     case ptGT_Choice :
630       m_Hash[Key]->GuiChoice->SetValue(Value);
631       break;
632     case ptGT_Check :
633       m_Hash[Key]->GuiCheck->SetValue(Value);
634       break;
635     default:
636       assert(m_Hash[Key]->GuiType == ptGT_None); // Else we missed a gui one
637       break;
638   }
639 }
640 
641 ////////////////////////////////////////////////////////////////////////////////
642 //
643 // SetEnabled
644 // Enable the underlying gui element (if one)
645 //
646 ////////////////////////////////////////////////////////////////////////////////
647 
SetEnabled(const QString Key,const short Enabled)648 void ptSettings::SetEnabled(const QString Key, const short Enabled) {
649   if (!m_Hash.contains(Key)) {
650     ptLogError(ptError_Argument,
651                "(%s,%d) Could not find key '%s'\n",
652                __FILE__,__LINE__,Key.toLocal8Bit().data());
653     assert (m_Hash.contains(Key));
654   }
655   switch (m_Hash[Key]->GuiType) {
656     case ptGT_Input :
657     case ptGT_InputSlider :
658     case ptGT_InputSliderHue :
659       m_Hash[Key]->GuiInput->SetEnabled(Enabled);
660       break;
661     case ptGT_Choice :
662       m_Hash[Key]->GuiChoice->SetEnabled(Enabled);
663       break;
664     case ptGT_Check :
665       m_Hash[Key]->GuiCheck->SetEnabled(Enabled);
666       break;
667     default:
668       ptLogError(ptError_Argument,
669                  "%s is no (expected) gui element.",
670                  Key.toLocal8Bit().data());
671       assert(m_Hash[Key]->GuiType); // Should have gui type !
672       break;
673   }
674 }
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 //
678 // SetMaximum
679 // Makes only sense for gui input element, which is asserted.
680 //
681 ////////////////////////////////////////////////////////////////////////////////
682 
SetMaximum(const QString Key,const QVariant Maximum)683 void ptSettings::SetMaximum(const QString Key, const QVariant Maximum) {
684   if (!m_Hash.contains(Key)) {
685     ptLogError(ptError_Argument,
686                "Could not find key '%s'\n",
687                Key.toLocal8Bit().data());
688     assert (m_Hash.contains(Key));
689   }
690   if (!m_Hash[Key]->GuiInput) {
691     ptLogError(ptError_Argument,
692                "Key '%s' has no initialized GuiInput\n",
693                Key.toLocal8Bit().data());
694     assert (m_Hash[Key]->GuiChoice);
695   }
696   return m_Hash[Key]->GuiInput->SetMaximum(Maximum);
697 }
698 
699 ////////////////////////////////////////////////////////////////////////////////
700 //
701 // Show (or hide)
702 // Makes only sense for gui element, which is asserted.
703 //
704 ////////////////////////////////////////////////////////////////////////////////
705 
Show(const QString Key,const short Show)706 void  ptSettings::Show(const QString Key, const short Show) {
707   if (!m_Hash.contains(Key)) {
708     ptLogError(ptError_Argument,
709                "(%s,%d) Could not find key '%s'\n",
710                __FILE__,__LINE__,Key.toLocal8Bit().data());
711     assert (m_Hash.contains(Key));
712   }
713   switch (m_Hash[Key]->GuiType) {
714     case ptGT_Input :
715     case ptGT_InputSlider :
716     case ptGT_InputSliderHue :
717       m_Hash[Key]->GuiInput->Show(Show);
718       break;
719     case ptGT_Choice :
720       m_Hash[Key]->GuiChoice->Show(Show);
721       break;
722     case ptGT_Check :
723       m_Hash[Key]->GuiCheck->Show(Show);
724       break;
725     default:
726       ptLogError(ptError_Argument,
727                  "%s is no (expected) gui element.",
728                  Key.toLocal8Bit().data());
729       assert(m_Hash[Key]->GuiType);
730       break;
731   }
732 }
733 
734 ////////////////////////////////////////////////////////////////////////////////
735 //
736 // AddOrReplaceOption
737 // Makes only sense for gui choice (combo) element, which is asserted.
738 //
739 ////////////////////////////////////////////////////////////////////////////////
740 
AddOrReplaceOption(const QString Key,const QString Text,const QVariant Value)741 void ptSettings::AddOrReplaceOption(const QString  Key,
742                                     const QString  Text,
743                                     const QVariant Value) {
744   // In job mode there are no gui elements and we have to return.
745   if (GetInt("JobMode")) return;
746   if (!m_Hash.contains(Key)) {
747     ptLogError(ptError_Argument,
748                "Could not find key '%s'\n",
749                Key.toLocal8Bit().data());
750     assert (m_Hash.contains(Key));
751   }
752   if (!m_Hash[Key]->GuiChoice) {
753     ptLogError(ptError_Argument,
754                "Key '%s' has no initialized GuiChoice\n",
755                Key.toLocal8Bit().data());
756     assert (m_Hash[Key]->GuiChoice);
757   }
758   m_Hash[Key]->GuiChoice->AddOrReplaceItem(Text,Value);
759 }
760 
761 ////////////////////////////////////////////////////////////////////////////////
762 //
763 // ClearOptions
764 // Makes only sense for gui choice (combo) element, which is asserted.
765 //
766 ////////////////////////////////////////////////////////////////////////////////
767 
ClearOptions(const QString Key,const short WithDefault)768 void ptSettings::ClearOptions(const QString  Key, const short WithDefault) {
769   // In job mode there are no gui elements and we have to return.
770   if (GetInt("JobMode")) return;
771   if (!m_Hash.contains(Key)) {
772     ptLogError(ptError_Argument,
773                "Could not find key '%s'\n",
774                Key.toLocal8Bit().data());
775     assert (m_Hash.contains(Key));
776   }
777   if (!m_Hash[Key]->GuiChoice) {
778     ptLogError(ptError_Argument,
779                "Key '%s' has no initialized GuiChoice\n",
780                Key.toLocal8Bit().data());
781     assert (m_Hash[Key]->GuiChoice);
782   }
783   m_Hash[Key]->GuiChoice->Clear(WithDefault);
784 }
785 
786 ////////////////////////////////////////////////////////////////////////////////
787 //
788 // GetNrOptions
789 // Makes only sense for gui choice (combo) element, which is asserted.
790 //
791 ////////////////////////////////////////////////////////////////////////////////
792 
GetNrOptions(const QString Key)793 int ptSettings::GetNrOptions(const QString Key) {
794   if (!m_Hash.contains(Key)) {
795     ptLogError(ptError_Argument,
796                "Could not find key '%s'\n",
797                Key.toLocal8Bit().data());
798     assert (m_Hash.contains(Key));
799   }
800   if (!m_Hash[Key]->GuiChoice) {
801     ptLogError(ptError_Argument,
802                "Key '%s' has no initialized GuiChoice\n",
803                Key.toLocal8Bit().data());
804     assert (m_Hash[Key]->GuiChoice);
805   }
806   return m_Hash[Key]->GuiChoice->Count();
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 //
811 // GetOptionsValue (at index Index)
812 // Makes only sense for gui choice (combo) element, which is asserted.
813 //
814 ////////////////////////////////////////////////////////////////////////////////
815 
GetOptionsValue(const QString Key,const int Index)816 const QVariant ptSettings::GetOptionsValue(const QString Key,const int Index){
817   if (!m_Hash.contains(Key)) {
818     ptLogError(ptError_Argument,
819                "Could not find key '%s'\n",
820                Key.toLocal8Bit().data());
821     assert (m_Hash.contains(Key));
822   }
823   if (!m_Hash[Key]->GuiChoice) {
824     ptLogError(ptError_Argument,
825                "Key '%s' has no initialized GuiChoice\n",
826                Key.toLocal8Bit().data());
827     assert (m_Hash[Key]->GuiChoice);
828   }
829   return m_Hash[Key]->GuiChoice->GetItemData(Index);
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 //
834 // GetCurrentText
835 // Makes only sense for gui choice (combo) element, which is asserted.
836 //
837 ////////////////////////////////////////////////////////////////////////////////
838 
GetCurrentText(const QString Key)839 const QString ptSettings::GetCurrentText(const QString Key){
840   if (!m_Hash.contains(Key)) {
841     ptLogError(ptError_Argument,
842                "Could not find key '%s'\n",
843                Key.toLocal8Bit().data());
844     assert (m_Hash.contains(Key));
845   }
846   if (!m_Hash[Key]->GuiChoice) {
847     ptLogError(ptError_Argument,
848                "Key '%s' has no initialized GuiChoice\n",
849                Key.toLocal8Bit().data());
850     assert (m_Hash[Key]->GuiChoice);
851   }
852   return m_Hash[Key]->GuiChoice->CurrentText();
853 }
854 
855 ////////////////////////////////////////////////////////////////////////////////
856 //
857 // SetGuiInput
858 //
859 ////////////////////////////////////////////////////////////////////////////////
860 
SetGuiInput(const QString Key,ptInput * Value)861 void ptSettings::SetGuiInput(const QString Key, ptInput* Value) {
862   if (!m_Hash.contains(Key)) {
863     ptLogError(ptError_Argument,
864                "(%s,%d) Could not find key '%s'\n",
865                __FILE__,__LINE__,Key.toLocal8Bit().data());
866     assert (m_Hash.contains(Key));
867   }
868   m_Hash[Key]->GuiInput  = Value;
869   m_Hash[Key]->GuiChoice = NULL;
870   m_Hash[Key]->GuiCheck  = NULL;
871 }
872 
873 ////////////////////////////////////////////////////////////////////////////////
874 //
875 // SetGuiChoice
876 //
877 ////////////////////////////////////////////////////////////////////////////////
878 
SetGuiChoice(const QString Key,ptChoice * Value)879 void ptSettings::SetGuiChoice(const QString Key, ptChoice* Value) {
880   if (!m_Hash.contains(Key)) {
881     ptLogError(ptError_Argument,
882                "(%s,%d) Could not find key '%s'\n",
883                __FILE__,__LINE__,Key.toLocal8Bit().data());
884     assert (m_Hash.contains(Key));
885   }
886   m_Hash[Key]->GuiInput  = NULL;
887   m_Hash[Key]->GuiChoice = Value;
888   m_Hash[Key]->GuiCheck  = NULL;
889 }
890 
891 ////////////////////////////////////////////////////////////////////////////////
892 //
893 // SetGuiCheck
894 //
895 ////////////////////////////////////////////////////////////////////////////////
896 
SetGuiCheck(const QString Key,ptCheck * Value)897 void ptSettings::SetGuiCheck(const QString Key, ptCheck* Value) {
898   if (!m_Hash.contains(Key)) {
899     ptLogError(ptError_Argument,
900                "(%s,%d) Could not find key '%s'\n",
901                __FILE__,__LINE__,Key.toLocal8Bit().data());
902     assert (m_Hash.contains(Key));
903   }
904   m_Hash[Key]->GuiInput  = NULL;
905   m_Hash[Key]->GuiChoice = NULL;
906   m_Hash[Key]->GuiCheck  = Value;
907 }
908 
909 ////////////////////////////////////////////////////////////////////////////////
910 //
911 // GetGuiWidget
912 // low level access to the underlying QWidget
913 //
914 ////////////////////////////////////////////////////////////////////////////////
915 
GetGuiWidget(const QString Key)916 QWidget* ptSettings::GetGuiWidget(const QString Key) {
917   if (!m_Hash.contains(Key)) {
918     ptLogError(ptError_Argument,
919                "(%s,%d) Could not find key '%s'\n",
920                __FILE__,__LINE__,Key.toLocal8Bit().data());
921     assert (m_Hash.contains(Key));
922   }
923   if (m_Hash[Key]->GuiInput) {
924     return (QWidget*)m_Hash[Key]->GuiInput;
925   } else if (m_Hash[Key]->GuiChoice) {
926     return (QWidget*)m_Hash[Key]->GuiChoice;
927   } else if (m_Hash[Key]->GuiCheck) {
928     return (QWidget*)m_Hash[Key]->GuiCheck;
929   }
930 
931   assert (!"No Gui widget");
932   return NULL;
933 }
934 
935 ////////////////////////////////////////////////////////////////////////////////
936 //
937 // Transfer the settings from Settings To DcRaw UserSettings.
938 // This is sometimes not straightforward as DcRaw assumes certain
939 // combinations. That's taken care of here.
940 //
941 ////////////////////////////////////////////////////////////////////////////////
942 
ToDcRaw(ptDcRaw * TheDcRaw)943 void ptSettings::ToDcRaw(ptDcRaw* TheDcRaw) {
944 
945   if (!TheDcRaw) return;
946 
947   // Relying on m_PipeSize being as defined in the constants ! (1<<Size)
948   TheDcRaw->m_UserSetting_HalfSize = GetInt("PipeSize");
949 
950   // Input file name
951 
952   QString InputFileName = GetStringList("InputFileNameList")[0];
953   FREE(TheDcRaw->m_UserSetting_InputFileName);
954   TheDcRaw->m_UserSetting_InputFileName =
955     (char*) MALLOC(1+strlen(InputFileName.toLocal8Bit().data()));
956   ptMemoryError(TheDcRaw->m_UserSetting_InputFileName,__FILE__,__LINE__);
957   strcpy(TheDcRaw->m_UserSetting_InputFileName,InputFileName.toLocal8Bit().data());
958 
959   // Detail view
960   TheDcRaw->m_UserSetting_DetailView = Settings->GetInt("DetailViewActive");
961   TheDcRaw->m_UserSetting_DetailViewCropX = Settings->GetInt("DetailViewCropX");
962   TheDcRaw->m_UserSetting_DetailViewCropY = Settings->GetInt("DetailViewCropY");
963   TheDcRaw->m_UserSetting_DetailViewCropW = Settings->GetInt("DetailViewCropW");
964   TheDcRaw->m_UserSetting_DetailViewCropH = Settings->GetInt("DetailViewCropH");
965 
966   // Adjust Maximum
967   TheDcRaw->m_UserSetting_AdjustMaximum = GetDouble("AdjustMaximumThreshold");
968 
969   // Denoise.
970   TheDcRaw->m_UserSetting_DenoiseThreshold = GetInt("RawDenoiseThreshold");
971 
972   // Hotpixel reduction
973   TheDcRaw->m_UserSetting_HotpixelReduction = GetDouble("HotpixelReduction");
974 
975   // Bayer denoise
976   TheDcRaw->m_UserSetting_BayerDenoise = GetInt("BayerDenoise");
977 
978   // Green equilibration
979   TheDcRaw->m_UserSetting_GreenEquil = GetInt("GreenEquil");
980 
981   // CA auto correction
982   TheDcRaw->m_UserSetting_CaCorrect = GetInt("CaCorrect");
983   TheDcRaw->m_UserSetting_CaRed = GetDouble("CaRed");
984   TheDcRaw->m_UserSetting_CaBlue = GetDouble("CaBlue");
985 
986   // CFA Line denoise
987   TheDcRaw->m_UserSetting_CfaLineDn = GetInt("CfaLineDenoise");
988 
989   // Interpolation
990   TheDcRaw->m_UserSetting_Quality = GetInt("Interpolation");
991 
992   // White balance settings.
993   switch (GetInt("WhiteBalance")) {
994     case ptWhiteBalance_Camera :
995       TheDcRaw->m_UserSetting_CameraWb = 1;
996       TheDcRaw->m_UserSetting_AutoWb   = 0;
997       TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
998       TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
999       TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1000       TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1001       TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1002       TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1003       TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1004       TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1005       break;
1006     case ptWhiteBalance_Auto :
1007       TheDcRaw->m_UserSetting_CameraWb = 0;
1008       TheDcRaw->m_UserSetting_AutoWb   = 1;
1009       TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
1010       TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
1011       TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1012       TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1013       TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1014       TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1015       TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1016       TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1017       break;
1018     case ptWhiteBalance_Spot :
1019       TheDcRaw->m_UserSetting_CameraWb = 0;
1020       TheDcRaw->m_UserSetting_AutoWb   = 1; // GreyBox must have auto on !
1021       TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
1022       TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
1023       TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1024       TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1025 
1026       // The selection, which is in preview coordinates, must
1027       // be transformed back to the original.
1028       // Express always in size of original image !
1029       // Also take into account TheDcRaw->m_Flip
1030 
1031       { // Jump to case label issue.
1032       int TmpPipeSize = GetInt("PipeSize");
1033       uint16_t X = (1<<TmpPipeSize) * GetInt("VisualSelectionX");
1034       uint16_t Y = (1<<TmpPipeSize) * GetInt("VisualSelectionY");
1035       uint16_t W = (1<<TmpPipeSize) * GetInt("VisualSelectionWidth");
1036       uint16_t H = (1<<TmpPipeSize) * GetInt("VisualSelectionHeight");
1037 
1038       uint16_t TargetW = W;
1039       uint16_t TargetH = H;
1040       if (TheDcRaw->m_Flip & 4) {
1041         SWAP(X,Y);
1042         SWAP(TargetW,TargetH);
1043       }
1044       if (TheDcRaw->m_Flip & 2) Y = GetInt("ImageH")-1-Y-TargetH;
1045       if (TheDcRaw->m_Flip & 1) X = GetInt("ImageW")-1-X-TargetW;
1046       TheDcRaw->m_UserSetting_GreyBox[0] = X;
1047       TheDcRaw->m_UserSetting_GreyBox[1] = Y;
1048       TheDcRaw->m_UserSetting_GreyBox[2] = TargetW;
1049       TheDcRaw->m_UserSetting_GreyBox[3] = TargetH;
1050       }
1051 
1052       TRACEKEYVALS("GreyBox[0]","%d",TheDcRaw->m_UserSetting_GreyBox[0]);
1053       TRACEKEYVALS("GreyBox[1]","%d",TheDcRaw->m_UserSetting_GreyBox[1]);
1054       TRACEKEYVALS("GreyBox[2]","%d",TheDcRaw->m_UserSetting_GreyBox[2]);
1055       TRACEKEYVALS("GreyBox[3]","%d",TheDcRaw->m_UserSetting_GreyBox[3]);
1056 
1057       break;
1058     default : // this entails as well manual as preset from ptWhiteBalances.
1059       TheDcRaw->m_UserSetting_CameraWb = 0;
1060       TheDcRaw->m_UserSetting_AutoWb   = 0;
1061       TheDcRaw->m_UserSetting_Multiplier[0]= GetDouble("RMultiplier");
1062       TheDcRaw->m_UserSetting_Multiplier[1]= GetDouble("GMultiplier");
1063       TheDcRaw->m_UserSetting_Multiplier[2] =GetDouble("BMultiplier");
1064       TheDcRaw->m_UserSetting_Multiplier[3] =
1065         TheDcRaw->m_Colors == 4 ? GetDouble("GMultiplier") : 0.0;
1066       TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1067       TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1068       TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1069       TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1070   }
1071 
1072   // Bad pixels settings.
1073   switch(GetInt("HaveBadPixels")) {
1074     case 0 : // None
1075       TheDcRaw->m_UserSetting_BadPixelsFileName = NULL;
1076       break;
1077     case 1 : // Load one : should not happen !
1078       assert(0);
1079       break;
1080     case 2 :
1081       FREE(TheDcRaw->m_UserSetting_BadPixelsFileName);
1082       TheDcRaw->m_UserSetting_BadPixelsFileName = (char *)
1083         MALLOC(1+
1084              strlen(GetString("BadPixelsFileName").toLocal8Bit().data()));
1085       ptMemoryError(TheDcRaw->m_UserSetting_BadPixelsFileName,
1086                     __FILE__,__LINE__);
1087       strcpy(TheDcRaw->m_UserSetting_BadPixelsFileName,
1088              GetString("BadPixelsFileName").toLocal8Bit().data());
1089       break;
1090     default :
1091       assert(0);
1092   }
1093 
1094   // Dark frame settings.
1095   switch(GetInt("HaveDarkFrame")) {
1096     case 0 : // None
1097       TheDcRaw->m_UserSetting_DarkFrameFileName = NULL;
1098       break;
1099     case 1 : // Load one : should not happen !
1100       assert(0);
1101       break;
1102     case 2 :
1103       FREE(TheDcRaw->m_UserSetting_DarkFrameFileName);
1104       TheDcRaw->m_UserSetting_DarkFrameFileName = (char *)
1105         MALLOC(1+
1106              strlen(GetString("DarkFrameFileName").toLocal8Bit().data()));
1107       ptMemoryError(TheDcRaw->m_UserSetting_DarkFrameFileName,
1108                     __FILE__,__LINE__);
1109       strcpy(TheDcRaw->m_UserSetting_DarkFrameFileName,
1110              GetString("DarkFrameFileName").toLocal8Bit().data());
1111       break;
1112     default :
1113       assert(0);
1114   }
1115 
1116   // Blackpoint settings.
1117   switch (GetInt("ManualBlackPoint")) {
1118     case 0 : // Automatic.
1119       TheDcRaw->m_UserSetting_BlackPoint = -1;
1120       break;
1121     default : // Manual set
1122       TheDcRaw->m_UserSetting_BlackPoint = GetInt("BlackPoint");
1123       break;
1124   }
1125 
1126   // Whitepoint settings.
1127   switch (GetInt("ManualWhitePoint")) {
1128     case 0 : // Automatic.
1129       TheDcRaw->m_UserSetting_Saturation = -1;
1130       break;
1131     default : // Manual set
1132       TheDcRaw->m_UserSetting_Saturation = GetInt("WhitePoint");
1133       break;
1134   }
1135   // Normalization of Multipliers
1136   TheDcRaw->m_UserSetting_MaxMultiplier = GetInt("MultiplierEnhance");
1137 
1138   // Interpolation passes.
1139   TheDcRaw->m_UserSetting_InterpolationPasses = GetInt("InterpolationPasses");
1140 
1141   // Median Filter.
1142   TheDcRaw->m_UserSetting_MedianPasses = GetInt("MedianPasses");
1143   TheDcRaw->m_UserSetting_ESMedianPasses = GetInt("ESMedianPasses");
1144   TheDcRaw->m_UserSetting_EeciRefine = GetInt("EeciRefine");
1145 
1146   // Clip factor
1147   TheDcRaw->m_UserSetting_photivo_ClipMode       = GetInt("ClipMode");
1148   TheDcRaw->m_UserSetting_photivo_ClipParameter  = GetInt("ClipParameter");
1149 }
1150 
1151 ////////////////////////////////////////////////////////////////////////////////
1152 //
1153 // Transfers the settings from DcRaw back to the Gui.
1154 // In some situations , DcRaw can overwrite or calculate values.
1155 // The output of those are here fed back to the Gui settings such
1156 // that they are correctly reflected.
1157 //
1158 ////////////////////////////////////////////////////////////////////////////////
1159 
FromDcRaw(ptDcRaw * TheDcRaw)1160 void ptSettings::FromDcRaw(ptDcRaw* TheDcRaw) {
1161 
1162   if (!TheDcRaw) return;
1163 
1164   // Copy make and model to our gui settings (f.i.
1165   // white balances rely on it)
1166   SetValue("CameraMake",TheDcRaw->m_CameraMake);
1167   SetValue("CameraModel",TheDcRaw->m_CameraModel);
1168 
1169   // Reset spot white balance
1170   if (GetInt("WhiteBalance") == ptWhiteBalance_Spot)
1171     SetValue("WhiteBalance", ptWhiteBalance_Manual);
1172 
1173   // Multipliers.
1174   SetValue("RMultiplier",VALUE(TheDcRaw->m_PreMultipliers[0]));
1175   SetValue("GMultiplier",VALUE(TheDcRaw->m_PreMultipliers[1]));
1176   SetValue("BMultiplier",VALUE(TheDcRaw->m_PreMultipliers[2]));
1177 
1178   // (D65) Multipliers to ColorTemperature.
1179   //
1180   // m_D65Multipliers are supposed to be D65
1181   // (setting Pre to the ratio of the D65 delivers
1182   // rgbWB = (x,x,x) and 6500 temperature).
1183 
1184   double RefRGB[3];
1185   if (TheDcRaw->m_RawColorPhotivo) {
1186     for (short c=0; c<3; c++) {
1187       RefRGB[c] = VALUE(TheDcRaw->m_D65Multipliers[c]) /
1188                   VALUE(TheDcRaw->m_PreMultipliers[c]);
1189     }
1190   } else {
1191     // If not raw, we have to calculate back sRGB references to the cam rgb.
1192     for (short c=0; c<3; c++) {
1193       RefRGB[c] = 0;
1194       for (short cc=0; cc<TheDcRaw->m_Colors ; cc++) {
1195         RefRGB[c] += TheDcRaw->m_MatrixCamRGBToSRGB[c][cc] *
1196                      VALUE(TheDcRaw->m_D65Multipliers[cc]) /
1197                      VALUE(TheDcRaw->m_PreMultipliers[cc]);
1198       }
1199     }
1200   }
1201 
1202   int    TmpColorTemperature;
1203   double TmpGreenIntensity;
1204   RGBToTemperature(RefRGB,
1205                    &TmpColorTemperature,
1206                    &TmpGreenIntensity);
1207   SetValue("ColorTemperature",TmpColorTemperature);
1208   SetValue("GreenIntensity",TmpGreenIntensity);
1209 
1210   // Blackpoint setting in case not manual.
1211   if (!GetInt("ManualBlackPoint")) {
1212     SetValue("BlackPoint",TheDcRaw->m_BlackLevel_AfterPhase1);
1213   }
1214 
1215   // Whitepoint setting in case not manual.
1216   if (!GetInt("ManualWhitePoint")) {
1217     SetValue("WhitePoint",TheDcRaw->m_WhiteLevel_AfterPhase1);
1218   }
1219 
1220   double exposureNormalization = 1.0;
1221 
1222   // EOS exposure normalization might be a result of running DcRaw
1223   // (ie we have to normalize the exposure further in the flow.
1224   // TODO This is coming from ufraw. Seems fair, but no clue
1225   // what's the logic behind the calculation. Someone ?
1226   if (strcmp(TheDcRaw->m_CameraMake, "Canon")==0 &&
1227       strncmp(TheDcRaw->m_CameraModel, "EOS", 3)==0 ) {
1228     int Max = (int) VALUE(TheDcRaw->m_CameraMultipliers[0]);
1229     for (short c=1; c<TheDcRaw->m_Colors; c++) {
1230       if (VALUE(TheDcRaw->m_CameraMultipliers[c]) > Max) {
1231         Max = (int) VALUE(TheDcRaw->m_CameraMultipliers[c]);
1232       }
1233     }
1234     // The 100 is a pretty random value that makes sure above
1235     // was a 'right' number calculated and it's not bogus
1236     // due to for instance not being able reading CamMultipliers
1237     if ( Max > 100 ) {
1238       exposureNormalization =
1239         (4096.0-TheDcRaw->m_BlackLevel_AfterPhase1)/Max;
1240     }
1241   }
1242 
1243   TRACEKEYVALS("EOSExposureNorm","%f",exposureNormalization);
1244 
1245   SetValue("ExposureNormalization",
1246            // EV conversion !
1247            log(exposureNormalization/TheDcRaw->m_MinPreMulti)/log(2));
1248 
1249   TRACEKEYVALS("ExposureNorm(EV)","%f", GetDouble("ExposureNormalization"));
1250 }
1251 
1252 //==============================================================================
1253 
useRAWHandling() const1254 bool ptSettings::useRAWHandling() const
1255 {
1256   return (GetInt("IsRAW") == 1) && (GetInt("UseThumbnail") == 0);
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 //
1261 // Tool Info
1262 // IsActive contains, if the filter will be processed!
1263 //
1264 ////////////////////////////////////////////////////////////////////////////////
1265 
1266 struct sToolInfo {
1267   QString               Name;
1268   short                 IsActive;
1269   short                 IsHidden;
1270   short                 IsBlocked;
1271   short                 IsDisabled;
1272 };
1273 
ToolInfo(const QString GuiName)1274 sToolInfo ToolInfo (const QString GuiName) {
1275   sToolInfo Info = {"N.N.",0,0,0,0};
1276 
1277   // Tab Geometry
1278   if (GuiName == "TabLensfunCA") {
1279     Info.Name = "Chromatic Aberration (Lensfun)";
1280     Info.IsActive = Settings->GetInt("LfunCAModel") != 0;
1281   } else if (GuiName == "TabLensfunVignette") {
1282     Info.Name = "Vignetting (Lensfun)";
1283     Info.IsActive = Settings->GetInt("LfunVignetteModel") != 0;
1284   } else if (GuiName == "TabLensfunDistortion") {
1285     Info.Name = "Lens Distortion (Lensfun)";
1286     Info.IsActive = Settings->GetInt("LfunDistModel") != 0;
1287   } else if (GuiName == "TabLensfunGeometry") {
1288     Info.Name = "Geometry Conversion (Lensfun)";
1289     Info.IsActive = Settings->GetInt("LfunSrcGeo") != Settings->GetInt("LfunTargetGeo");
1290   } else if (GuiName == "TabDefish") {
1291       Info.Name = "Defish";
1292       Info.IsActive = Settings->GetInt("Defish");
1293   } else if (GuiName == "TabRotation") {
1294       Info.Name = "Rotation";
1295       Info.IsActive = (Settings->GetDouble("Rotate")!=0.0f ||
1296                        Settings->GetDouble("PerspectiveTilt")!=0.0f ||
1297                        Settings->GetDouble("PerspectiveTurn")!=0.0f ||
1298                        Settings->GetDouble("PerspectiveScaleX")!=1.0f ||
1299                        Settings->GetDouble("PerspectiveScaleY")!=1.0f)?1:0;
1300   } else if (GuiName == "TabLiquidRescale") {
1301       Info.Name = "Seam carving";
1302       Info.IsActive = Settings->GetInt("LqrEnergy");
1303   } else if (GuiName == "TabCrop") {
1304       Info.Name = "Crop";
1305       Info.IsActive = Settings->GetInt("Crop");
1306   } else if (GuiName == "TabResize") {
1307       Info.Name = "Resize";
1308       Info.IsActive = Settings->GetInt("Resize");
1309   } else if (GuiName == "TabFlip") {
1310       Info.Name = "Flip";
1311       Info.IsActive = Settings->GetInt("FlipMode");
1312   } else if (GuiName == "TabBlock") {
1313       Info.Name = "Block";
1314       Info.IsActive = !Settings->GetInt("JobMode") &&
1315                       Settings->GetInt("GeometryBlock");
1316   }
1317   // Tab Output
1318   else if (GuiName == "TabGammaCompensation") {
1319       Info.Name = "Output gamma compensation";
1320       Info.IsActive = Settings->GetInt("OutputGammaCompensation")!=0?1:0;
1321   } else if (GuiName == "TabWebResize") {
1322       Info.Name = "Output web resize";
1323       Info.IsActive = (Settings->GetInt("WebResize")==2 ||
1324                        (Settings->GetInt("FullOutput") &&
1325                         Settings->GetInt("WebResize")==1))!=0?1:0;
1326   }
1327 
1328   // tool blocked?
1329   Info.IsBlocked = (Settings->GetStringList("BlockedTools")).contains(GuiName)?1:0;
1330 
1331   // tool hidden?
1332   Info.IsHidden = (Settings->GetStringList("HiddenTools")).contains(GuiName)?1:0;
1333 
1334   // tool disabled?
1335   Info.IsDisabled = (Settings->GetStringList("DisabledTools")).contains(GuiName)?1:0;
1336   return Info;
1337 }
1338 
ToolAlwaysVisible(const QString GuiName) const1339 int ptSettings::ToolAlwaysVisible(const QString GuiName) const {
1340   QStringList VisibleTools =
1341   (QStringList()
1342     // Settings tab
1343     << "TabWorkColorSpace"
1344     << "TabPreviewColorSpace"
1345     << "TabUISettings"
1346     << "TabGimpCommand"
1347     << "TabRememberSettings"
1348     << "TabStartupSettings"
1349     << "TabCropSettings"
1350     << "TabInputControl"
1351     << "TabToolBoxControl"
1352     << "TabTabStatusIndicator"
1353     << "TabPreviewControl"
1354     << "TabTheming"
1355     << "TabConfigSaveMode"
1356     << "TabSearchBar"
1357     << "TabConfirmDialogs"
1358     << "TabBackupSettings"
1359     << "TabTranslation"
1360     << "TabMemoryTest"
1361     << "TabVisibleTools"
1362     << "TabFileMgrSettings"
1363     // Info tab
1364     << "TabInfoPhotivo"
1365     << "TabInfoFile"
1366     << "TabInfoExif"
1367     << "TabInfoSizes"
1368     // Input tab
1369     << "TabInput"
1370     << "TabCameraColorSpace"
1371     << "TabGenCorrections"
1372     << "TabWhiteBalance"
1373     << "TabDemosaicing"
1374     << "TabHighlightRecovery"
1375     // Output Tab
1376     << "TabOutputColorSpace"
1377     << "TabOutParameters"
1378     << "TabOutput");
1379   if (VisibleTools.contains(GuiName)) return 1;
1380   return 0;
1381 }
1382 
ToolGetName(const QString GuiName) const1383 QString ptSettings::ToolGetName (const QString GuiName) const {
1384   sToolInfo Info = ToolInfo(GuiName);
1385   return Info.Name;
1386 }
1387 
ToolIsActive(const QString GuiName) const1388 int ptSettings::ToolIsActive (const QString GuiName) const {
1389   sToolInfo Info = ToolInfo(GuiName);
1390   return (Info.IsHidden || Info.IsBlocked || Info.IsDisabled)?0:Info.IsActive;
1391 }
1392 
ToolIsBlocked(const QString GuiName) const1393 int ptSettings::ToolIsBlocked (const QString GuiName) const {
1394   sToolInfo Info = ToolInfo(GuiName);
1395   return Info.IsBlocked;
1396 }
1397 
ToolIsHidden(const QString GuiName) const1398 int ptSettings::ToolIsHidden (const QString GuiName) const {
1399   sToolInfo Info = ToolInfo(GuiName);
1400   return Info.IsHidden;
1401 }
1402 ///////////////////////////////////////////////////////////////////////////////
1403