diff --git a/.gitignore b/.gitignore index a049e4f..eccbb70 100644 --- a/.gitignore +++ b/.gitignore @@ -27,11 +27,3 @@ rawtherapee-3.0-a1.tar.bz2 /rawtherapee-5.6.tar.xz /rawtherapee-5.7.tar.xz /rawtherapee-5.8.tar.xz -/RawTherapee-68ec1a5bb50b496e255a0b843c36345fbeff2468.tar.gz -/RawTherapee-4059ae5bcad8e18443bf8f37bcff84de1dcc0d03.tar.gz -/rawtherapee-5.9.tar.xz -/rawtherapee-5.10-rc1.tar.xz -/rawtherapee-5.10.tar.xz -/rawtherapee-5.11.tar.xz -/rawtherapee-5.12-rc1.tar.xz -/rawtherapee-5.12.tar.xz diff --git a/0001-Fix-static-init-order-fiasco-crashes.patch b/0001-Fix-static-init-order-fiasco-crashes.patch deleted file mode 100644 index 15f483c..0000000 --- a/0001-Fix-static-init-order-fiasco-crashes.patch +++ /dev/null @@ -1,5810 +0,0 @@ -From 9ce6a4dd297d47044c15936c89cb27f3d5cf94bf Mon Sep 17 00:00:00 2001 -From: Daniel Gao -Date: Sun, 29 Jun 2025 15:08:54 -0400 -Subject: [PATCH] Fix static init order fiasco crashes - -- Fix read before initialize of options.rtSettings.srgb -- Use Meyer's singleton for default cmp -- Group extern variables into App singleton -- Fix recursive init and build issues -- Fix Apple build ---- - rtengine/CMakeLists.txt | 3 +- - rtengine/FTblockDN.cc | 13 +- - rtengine/clutstore.cc | 4 +- - rtengine/dcp.cc | 9 +- - rtengine/dfmanager.cc | 2 + - rtengine/dual_demosaic_RT.cc | 1 + - rtengine/ffmanager.cc | 2 + - rtengine/iccstore.cc | 2 + - rtengine/imageio.cc | 2 +- - rtengine/improccoordinator.cc | 9 +- - rtengine/ipwavelet.cc | 5 +- - rtengine/pixelshift.cc | 2 + - rtengine/procparams.cc | 18 ++- - rtengine/profilestore.cc | 7 +- - rtengine/rawimagesource.cc | 2 + - rtengine/rtapp.cc | 57 ++++++++ - rtengine/rtapp.h | 81 ++++++++++++ - rtengine/simpleprocess.cc | 1 + - rtgui/adjuster.cc | 4 +- - rtgui/batchqueue.cc | 25 ++-- - rtgui/batchqueueentry.cc | 1 + - rtgui/batchqueuepanel.cc | 15 ++- - rtgui/batchtoolpanelcoord.cc | 2 + - rtgui/bayerpreprocess.cc | 3 +- - rtgui/bayerprocess.cc | 3 +- - rtgui/bayerrawexposure.cc | 3 +- - rtgui/blackwhite.cc | 1 + - rtgui/bqentryupdater.cc | 1 + - rtgui/cachemanager.cc | 7 +- - rtgui/colorappearance.cc | 2 + - rtgui/colortoning.cc | 2 + - rtgui/controlspotpanel.cc | 6 +- - rtgui/crop.cc | 4 +- - rtgui/cropwindow.cc | 14 +- - rtgui/curveeditorgroup.cc | 3 +- - rtgui/curveeditorgroup.h | 2 +- - rtgui/darkframe.cc | 2 + - rtgui/defringe.cc | 1 + - rtgui/diagonalcurveeditorsubgroup.cc | 1 + - rtgui/dirbrowser.cc | 7 +- - rtgui/dirpyrdenoise.cc | 5 +- - rtgui/editorpanel.cc | 66 ++++++---- - rtgui/editwindow.cc | 9 +- - rtgui/exportpanel.cc | 3 + - rtgui/extprog.cc | 4 +- - rtgui/filebrowser.cc | 28 ++-- - rtgui/filebrowserentry.cc | 6 +- - rtgui/filecatalog.cc | 190 +++++++++++++++------------ - rtgui/filepanel.cc | 14 +- - rtgui/filmnegative.cc | 3 + - rtgui/filmsimulation.cc | 10 +- - rtgui/flatcurveeditorsubgroup.cc | 1 + - rtgui/flatfield.cc | 3 + - rtgui/guiutils.cc | 5 +- - rtgui/histogrampanel.cc | 66 +++++----- - rtgui/hsvequalizer.cc | 2 +- - rtgui/iccprofilecreator.cc | 33 ++--- - rtgui/icmpanel.cc | 4 +- - rtgui/imagearea.cc | 9 +- - rtgui/indclippedpanel.cc | 1 + - rtgui/inspector.cc | 4 + - rtgui/labcurve.cc | 2 +- - rtgui/labgrid.cc | 1 + - rtgui/lensprofile.cc | 3 +- - rtgui/locallab.cc | 4 +- - rtgui/locallabtools.cc | 61 +++++---- - rtgui/locallabtools2.cc | 80 ++++++----- - rtgui/lockablecolorpicker.cc | 11 +- - rtgui/main-cli.cc | 57 ++++---- - rtgui/main.cc | 96 ++++++-------- - rtgui/navigator.cc | 17 +-- - rtgui/options.cc | 148 ++++++++++----------- - rtgui/options.h | 34 ++--- - rtgui/paramsedited.cc | 3 + - rtgui/pdsharpening.cc | 1 + - rtgui/placesbrowser.cc | 3 + - rtgui/preferences.cc | 22 ++-- - rtgui/preprocess.cc | 3 +- - rtgui/previewmodepanel.cc | 1 + - rtgui/previewwindow.cc | 2 + - rtgui/profilepanel.cc | 18 +-- - rtgui/profilestorecombobox.cc | 2 +- - rtgui/rawcacorrection.cc | 1 + - rtgui/rawexposure.cc | 1 + - rtgui/recentbrowser.cc | 3 +- - rtgui/retinex.cc | 2 + - rtgui/rgbcurves.cc | 1 + - rtgui/rtscalable.cc | 7 +- - rtgui/rtwindow.cc | 58 ++++---- - rtgui/saveasdlg.cc | 7 +- - rtgui/saveformatpanel.cc | 2 +- - rtgui/saveformatpanel.h | 2 +- - rtgui/sharpenedge.cc | 1 + - rtgui/soundman.cc | 2 +- - rtgui/splash.cc | 15 +-- - rtgui/thresholdadjuster.cc | 2 +- - rtgui/thumbbrowserbase.cc | 10 +- - rtgui/thumbbrowserbase.h | 2 +- - rtgui/thumbbrowserentrybase.cc | 5 + - rtgui/thumbnail.cc | 48 ++++--- - rtgui/tonecurve.cc | 1 + - rtgui/toolpanelcoord.cc | 7 + - rtgui/vibrance.cc | 1 + - rtgui/wavelet.cc | 28 ++-- - rtgui/whitebalance.cc | 5 +- - rtgui/xtransprocess.cc | 3 +- - rtgui/xtransrawexposure.cc | 1 + - 107 files changed, 942 insertions(+), 637 deletions(-) - create mode 100644 rtengine/rtapp.cc - create mode 100644 rtengine/rtapp.h - -diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt -index 6b388ced4..1ba1376f4 100644 ---- a/rtengine/CMakeLists.txt -+++ b/rtengine/CMakeLists.txt -@@ -175,6 +175,7 @@ set(RTENGINESOURCEFILES - rcd_demosaic.cc - refreshmap.cc - rt_algo.cc -+ rtapp.cc - rtlensfun.cc - rtthumbnail.cc - shmap.cc -@@ -245,7 +246,7 @@ target_include_directories(rtengine - ${CMAKE_CURRENT_SOURCE_DIR} - ) - # UpdateInfo creates "rtgui/version.h" --target_include_directories(rtengine BEFORE PRIVATE ${CMAKE_BINARY_DIR}) -+target_include_directories(rtengine BEFORE PUBLIC ${CMAKE_BINARY_DIR}) - - target_link_libraries(rtengine - ${EXPAT_LIBRARIES} -diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc -index 4a78e0602..2cd1c56b0 100644 ---- a/rtengine/FTblockDN.cc -+++ b/rtengine/FTblockDN.cc -@@ -710,6 +710,7 @@ BENCHFUN - - bool memoryAllocationFailed = false; - -+ const auto rgbDenoiseThreadLimit = App::get().options().rgbDenoiseThreadLimit; - do { - ++numTries; - -@@ -719,7 +720,7 @@ BENCHFUN - - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - -- Tile_calc(tilesize, overlap, (options.rgbDenoiseThreadLimit == 0 && !ponder) ? (numTries == 1 ? 0 : 2) : 2, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); -+ Tile_calc(tilesize, overlap, (rgbDenoiseThreadLimit == 0 && !ponder) ? (numTries == 1 ? 0 : 2) : 2, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - memoryAllocationFailed = false; - const int numtiles = numtiles_W * numtiles_H; - -@@ -783,8 +784,8 @@ BENCHFUN - // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles - int numthreads = MIN(numtiles, omp_get_max_threads()); - -- if (options.rgbDenoiseThreadLimit > 0) { -- numthreads = MIN(numthreads, options.rgbDenoiseThreadLimit); -+ if (rgbDenoiseThreadLimit > 0) { -+ numthreads = MIN(numthreads, rgbDenoiseThreadLimit); - } - - #ifdef _OPENMP -@@ -797,8 +798,8 @@ BENCHFUN - omp_set_nested(true); - } - -- if (options.rgbDenoiseThreadLimit > 0) -- while (denoiseNestedLevels * numthreads > options.rgbDenoiseThreadLimit) { -+ if (rgbDenoiseThreadLimit > 0) -+ while (denoiseNestedLevels * numthreads > rgbDenoiseThreadLimit) { - denoiseNestedLevels--; - } - -@@ -1764,7 +1765,7 @@ BENCHFUN - fftwf_destroy_plan(plan_forward_blox[1]); - fftwf_destroy_plan(plan_backward_blox[1]); - } -- } while (memoryAllocationFailed && numTries < 2 && (options.rgbDenoiseThreadLimit == 0) && !ponder); -+ } while (memoryAllocationFailed && numTries < 2 && (rgbDenoiseThreadLimit == 0) && !ponder); - - if (memoryAllocationFailed) { - printf("tiled denoise failed due to isufficient memory. Output is not denoised!\n"); -diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc -index db2216a8c..fb49d2e1c 100644 ---- a/rtengine/clutstore.cc -+++ b/rtengine/clutstore.cc -@@ -319,7 +319,7 @@ std::shared_ptr rtengine::CLUTStore::getClut(const Glib::ust - - const Glib::ustring full_filename = - !Glib::path_is_absolute(filename) -- ? Glib::ustring(Glib::build_filename(options.clutsDir, filename)) -+ ? Glib::ustring(Glib::build_filename(App::get().options().clutsDir, filename)) - : filename; - - if (!cache.get(full_filename, result)) { -@@ -340,6 +340,6 @@ void rtengine::CLUTStore::clearCache() - } - - rtengine::CLUTStore::CLUTStore() : -- cache(options.clutCacheSize) -+ cache(App::get().options().clutCacheSize) - { - } -diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc -index 3c6c54d33..43c882f2e 100644 ---- a/rtengine/dcp.cc -+++ b/rtengine/dcp.cc -@@ -2156,15 +2156,14 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) - - file_std_profiles.clear(); - -+ auto profile_dirpath = Glib::build_filename(App::get().options().rtdir, "dcpprofiles"); -+ - if (!loadAll) { -- profileDir = { rt_profile_dir, Glib::build_filename(options.rtdir, "dcpprofiles") }; -+ profileDir = { rt_profile_dir, profile_dirpath }; - return; - } - -- std::deque dirs = { -- rt_profile_dir, -- Glib::build_filename(options.rtdir, "dcpprofiles") -- }; -+ std::deque dirs = { rt_profile_dir, profile_dirpath }; - - while (!dirs.empty()) { - // Process directory -diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc -index 875517b24..c9b504940 100644 ---- a/rtengine/dfmanager.cc -+++ b/rtengine/dfmanager.cc -@@ -528,6 +528,8 @@ const std::vector* rtengine::DFManager::Implementation::getBad - - dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& filename, bool pool) - { -+ const Options& options = App::get().options(); -+ - const auto ext = getFileExtension(filename); - - if (ext.empty() || !options.is_extention_enabled(ext)) { -diff --git a/rtengine/dual_demosaic_RT.cc b/rtengine/dual_demosaic_RT.cc -index 749d07ed7..30ddb1a78 100644 ---- a/rtengine/dual_demosaic_RT.cc -+++ b/rtengine/dual_demosaic_RT.cc -@@ -40,6 +40,7 @@ namespace rtengine - - void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast) - { -+ const auto& options = App::get().options(); - - if (contrast == 0.0 && !autoContrast) { - // contrast == 0.0 means only first demosaicer will be used -diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc -index 984af1e82..89aaa847d 100644 ---- a/rtengine/ffmanager.cc -+++ b/rtengine/ffmanager.cc -@@ -302,6 +302,8 @@ void FFManager::init(const Glib::ustring& pathname) - - ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) - { -+ const Options& options = App::get().options(); -+ - auto ext = getFileExtension(filename); - - if (ext.empty() || !options.is_extention_enabled(ext)) { -diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc -index 96962e772..230199595 100644 ---- a/rtengine/iccstore.cc -+++ b/rtengine/iccstore.cc -@@ -453,6 +453,8 @@ public: - fileProfiles.clear(); - fileProfileContents.clear(); - -+ const auto& options = App::get().options(); -+ - if (loadAll) { - loadProfiles(profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); - loadProfiles(userICCDir, &fileProfiles, &fileProfileContents, nullptr, false); -diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc -index 1a1605334..bc34287f3 100644 ---- a/rtengine/imageio.cc -+++ b/rtengine/imageio.cc -@@ -688,7 +688,7 @@ int ImageIO::loadTIFF (const Glib::ustring &fname) - static MyMutex thumbMutex; - MyMutex::MyLock lock(thumbMutex); - -- if(!options.serializeTiffRead) { -+ if(!App::get().options().serializeTiffRead) { - lock.release(); - } - -diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc -index 376a67842..b0bf6879f 100644 ---- a/rtengine/improccoordinator.cc -+++ b/rtengine/improccoordinator.cc -@@ -338,7 +338,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) - // TODO Locallab printf - MyMutex::MyLock processingLock(mProcessing); - -- bool highDetailNeeded = options.prevdemo == PD_Sidecar ? true : (todo & M_HIGHQUAL); -+ const auto prevdemo = App::get().options().prevdemo; -+ bool highDetailNeeded = prevdemo == PD_Sidecar ? true : (todo & M_HIGHQUAL); - // printf("metwb=%s \n", params->wb.method.c_str()); - - // Check if any detail crops need high detail. If not, take a fast path short cut -@@ -351,7 +352,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) - } - } - -- if (((todo & ALL) == ALL) || (todo & M_MONITOR) || panningRelatedChange || (highDetailNeeded && options.prevdemo != PD_Sidecar)) { -+ if (((todo & ALL) == ALL) || (todo & M_MONITOR) || panningRelatedChange || (highDetailNeeded && prevdemo != PD_Sidecar)) { - bwAutoR = bwAutoG = bwAutoB = -9000.f; - - if (todo == CROP && ipf.needsPCVignetting()) { -@@ -2466,7 +2467,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) - - // process crop, if needed - for (size_t i = 0; i < crops.size(); i++) -- if (crops[i]->hasListener() && (panningRelatedChange || (highDetailNeeded && options.prevdemo != PD_Sidecar) || (todo & (M_MONITOR | M_RGBCURVE | M_LUMACURVE)) || crops[i]->get_skip() == 1)) { -+ if (crops[i]->hasListener() && (panningRelatedChange || (highDetailNeeded && prevdemo != PD_Sidecar) || (todo & (M_MONITOR | M_RGBCURVE | M_LUMACURVE)) || crops[i]->get_skip() == 1)) { - crops[i]->update(todo); // may call ourselves - } - -@@ -3342,7 +3343,7 @@ bool ImProcCoordinator::getHighQualComputed() - { - // this function may only be called from detail windows - if (!highQualityComputed) { -- if (options.prevdemo == PD_Sidecar) { -+ if (App::get().options().prevdemo == PD_Sidecar) { - // we already have high quality preview - setHighQualComputed(); - } else { -diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc -index d9d5fb2e4..85a6c13a4 100644 ---- a/rtengine/ipwavelet.cc -+++ b/rtengine/ipwavelet.cc -@@ -815,8 +815,9 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const - - - // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles -- if (options.rgbDenoiseThreadLimit > 0) { -- maxnumberofthreadsforwavelet = rtengine::LIM(options.rgbDenoiseThreadLimit / 2, 1, maxnumberofthreadsforwavelet); -+ const auto rgbDenoiseThreadLimit = App::get().options().rgbDenoiseThreadLimit; -+ if (rgbDenoiseThreadLimit > 0) { -+ maxnumberofthreadsforwavelet = rtengine::LIM(rgbDenoiseThreadLimit / 2, 1, maxnumberofthreadsforwavelet); - } - - numthreads = rtengine::min(numtiles, omp_get_max_threads()); -diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc -index bf17b9740..a01728820 100644 ---- a/rtengine/pixelshift.cc -+++ b/rtengine/pixelshift.cc -@@ -308,6 +308,8 @@ using namespace std; - using namespace rtengine; - void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const procparams::RAWParams &rawParamsIn, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection) - { -+ const auto& options = App::get().options(); -+ - BENCHFUN - if(numFrames != 4) { // fallback for non pixelshift files - amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); -diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc -index 2abb30593..a841c9221 100644 ---- a/rtengine/procparams.cc -+++ b/rtengine/procparams.cc -@@ -2713,7 +2713,7 @@ ColorManagementParams::ColorManagementParams() : - labgridcieMx(0.),// - labgridcieMy(0.),// - aRendIntent(RI_RELATIVE), -- outputProfile(options.rtSettings.srgb), -+ outputProfile(App::get().options().rtSettings.srgb), - outputIntent(RI_RELATIVE), - outputBPC(true) - { -@@ -3315,7 +3315,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : - avoidrad(0.), - transitweak(1.0), - transitgrad(0.0), -- hishow(options.complexity != 2), -+ hishow(App::get().options().complexity != 2), - activ(true), - avoidneg(true), - blwh(false), -@@ -5126,13 +5126,15 @@ LocallabParams::LocallabSpot::LocallabSpot() : - // init settings with Preferences / options : must be followed by call to spotMethodChanged in controlspotpanel.cc (idle_register) - // new values default with different SpotMethod. - -- if(options.spotmet == 3) {//global -+ const auto spotmet = App::get().options().spotmet; -+ -+ if(spotmet == 3) {//global - spotMethod = "main"; - loc = {3000, 3000, 3000, 3000}; - transit =100.; - shape = "RECT"; - -- } else if(options.spotmet == 2) {//full image -+ } else if(spotmet == 2) {//full image - spotMethod = "full"; - loc = {3000, 3000, 3000, 3000}; - transit =100.; -@@ -5153,7 +5155,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : - sensimask = 60; - sensicie = 60; - -- } else if(options.spotmet == 1) {//exclude -+ } else if(spotmet == 1) {//exclude - spotMethod = "exc"; - shape = "ELI"; - loc = {150, 150, 150, 150}; -@@ -5173,7 +5175,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : - sensimask = 60; - sensicie = 60; - -- } else if(options.spotmet == 0) {//normal -+ } else if(spotmet == 0) {//normal - spotMethod = "norm"; - shape = "ELI"; - loc = {150, 150, 150, 150}; -@@ -6735,6 +6737,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo - return 0; - } - -+ const auto& options = App::get().options(); -+ - Glib::ustring sPParams; - - try { -@@ -8670,6 +8674,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) - return 1; - } - -+ const auto& options = App::get().options(); -+ - Glib::KeyFile keyFile; - - try { -diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc -index 849e78165..555f30146 100644 ---- a/rtengine/profilestore.cc -+++ b/rtengine/profilestore.cc -@@ -126,6 +126,7 @@ void ProfileStore::_parseProfiles () - - folders.push_back ("<<< ROOT >>>"); // Fake path, so parentFolderId == 0 will be used to attach a ProfileStoreEntry to the root container, not sub-menu - -+ auto& options = App::get().mut_options(); - Glib::ustring p1 = options.getUserProfilePath(); - Glib::ustring p2 = options.getGlobalProfilePath(); - bool displayLevel0 = options.useBundledProfiles && !p1.empty() && !p2.empty() && p1 != p2; -@@ -221,7 +222,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath - } else { - size_t lastdot = currDir.find_last_of ('.'); - -- if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr (lastdot).casefold() == paramFileExtension) { -+ if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr (lastdot).casefold() == App::PARAM_FILE_EXTENSION) { - // file found - if (settings->verbose) { - printf ("Processing file %s...", fname.c_str()); -@@ -307,7 +308,7 @@ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU (Glib::ustring pat - if ( - lastdot_pos != Glib::ustring::npos - && lastdot_pos <= casefolded_path.size() - 4 -- && !casefolded_path.compare (lastdot_pos, 4, paramFileExtension) -+ && !casefolded_path.compare (lastdot_pos, 4, App::PARAM_FILE_EXTENSION) - ) { - // removing the extension - // now use dot position without casefold() -@@ -432,6 +433,7 @@ const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) - //Note: the mutex is locked in getProfile, called below - // eventual initialization is done there too - -+ const auto& options = App::get().options(); - const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - - if (!pProf) { -@@ -452,6 +454,7 @@ const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) - //Note: the mutex is locked in getProfile, called below - // eventual initialization is done there too - -+ const auto& options = App::get().options(); - const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - - if (!pProf) { -diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc -index c39ee4823..9a7fbefd3 100644 ---- a/rtengine/rawimagesource.cc -+++ b/rtengine/rawimagesource.cc -@@ -1759,6 +1759,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens - plistener->setProgress(0.0); - } - -+ const auto& options = App::get().options(); - if (numFrames == 4) { - double fitParams[64]; - float *buffer = CA_correct_RT(raw.ca_autocorrect, raw.caautoiterations, raw.cared, raw.cablue, raw.ca_avoidcolourshift, raw.bayersensor.border, *rawDataFrames[0], fitParams, false, true, nullptr, false, options.chunkSizeCA, options.measure); -@@ -1799,6 +1800,7 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c - MyTime t1, t2; - t1.set(); - -+ const auto& options = App::get().options(); - if (ri->getSensorType() == ST_BAYER) { - if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::HPHD)) { - hphd_demosaic(); -diff --git a/rtengine/rtapp.cc b/rtengine/rtapp.cc -new file mode 100644 -index 000000000..70358acc9 ---- /dev/null -+++ b/rtengine/rtapp.cc -@@ -0,0 +1,57 @@ -+/* -+ * This file is part of RawTherapee. -+ * -+ * Copyright (c) 2025 Daniel Gao -+ * -+ * 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 . -+ */ -+ -+#include "rtapp.h" -+ -+#include "rtengine/procparams.h" -+#include "rtengine/settings.h" -+#include "rtgui/options.h" -+#include "rtgui/version.h" -+ -+using namespace rtengine; -+ -+const Glib::ustring App::VERSION = RTVERSION; -+const Glib::ustring App::PARAM_FILE_EXTENSION = ".pp3"; -+ -+App& App::get() -+{ -+ static App inst; -+ return inst; -+} -+ -+App::App() -+ : m_options(new Options()) -+ , m_simple_editor(false) -+ , m_gimp_plugin(false) -+ , m_remote(false) -+{ -+} -+ -+const rtengine::Settings& App::settings() const -+{ -+ return m_options->rtSettings; -+} -+ -+const rtengine::procparams::ColorManagementParams& App::fallbackColorCmp() const -+{ -+ // Constructor accesses App::get().options(), so we can't initialize this -+ // in the constructor of App. It would be a recursive init. -+ static rtengine::procparams::ColorManagementParams cmp; -+ return cmp; -+} -diff --git a/rtengine/rtapp.h b/rtengine/rtapp.h -new file mode 100644 -index 000000000..2dc0ba6fb ---- /dev/null -+++ b/rtengine/rtapp.h -@@ -0,0 +1,81 @@ -+/* -+ * This file is part of RawTherapee. -+ * -+ * Copyright (c) 2025 Daniel Gao -+ * -+ * 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 . -+ */ -+ -+#pragma once -+ -+#include -+ -+#include -+ -+class Options; -+ -+namespace rtengine { -+class Settings; -+ -+namespace procparams { -+class ColorManagementParams; -+} // namespace procparams -+ -+} // namespace rtengine -+ -+class App { -+public: -+ static const Glib::ustring VERSION; -+ static const Glib::ustring PARAM_FILE_EXTENSION; -+ -+ static App& get(); -+ -+ const Options& options() const { return *m_options; } -+ Options& mut_options() { return *m_options; } -+ const rtengine::Settings& settings() const; -+ -+ const rtengine::procparams::ColorManagementParams& fallbackColorCmp() const; -+ -+ const Glib::ustring& argv0() const { return m_argv0; } -+ const Glib::ustring& argv1() const { return m_argv1; } -+ const Glib::ustring& creditsPath() const { return m_credits_path; } -+ const Glib::ustring& licensePath() const { return m_license_path; } -+ -+ bool isSimpleEditor() const { return m_simple_editor; } -+ bool isGimpPlugin() const { return m_gimp_plugin; } -+ bool isRemote() const { return m_remote; } -+ -+ void setArgv0(const Glib::ustring& val) { m_argv0 = val; } -+ void setArgv1(const Glib::ustring& val) { m_argv1 = val; } -+ void setCreditsPath(const Glib::ustring& path) { m_credits_path = path; } -+ void setLicensePath(const Glib::ustring& path) { m_license_path = path; } -+ -+ void setIsSimpleEditor(bool val) { m_simple_editor = val; } -+ void setIsGimpPlugin(bool val) { m_gimp_plugin = val; } -+ void setIsRemote(bool val) { m_remote = val; } -+ -+private: -+ App(); -+ -+ Glib::ustring m_argv0; -+ Glib::ustring m_argv1; -+ Glib::ustring m_credits_path; -+ Glib::ustring m_license_path; -+ -+ std::unique_ptr m_options; -+ -+ bool m_simple_editor; -+ bool m_gimp_plugin; -+ bool m_remote; -+}; -diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc -index c9307d623..04eea7735 100644 ---- a/rtengine/simpleprocess.cc -+++ b/rtengine/simpleprocess.cc -@@ -1457,6 +1457,7 @@ private: - - LUTu histToneCurve; - -+ const auto& options = App::get().options(); - ipf.rgbProc(baseImg, labView, nullptr, curve1, curve2, curve, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as, histToneCurve, options.chunkSizeRGB, options.measure); - - if (settings->verbose) { -diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc -index b126d91d9..1d7bc42e4 100644 ---- a/rtgui/adjuster.cc -+++ b/rtgui/adjuster.cc -@@ -55,8 +55,8 @@ Adjuster::Adjuster( - imageIcon2(imgIcon2), - automatic(nullptr), - adjusterListener(nullptr), -- spinChange(options.adjusterMinDelay, options.adjusterMaxDelay), -- sliderChange(options.adjusterMinDelay, options.adjusterMaxDelay), -+ spinChange(App::get().options().adjusterMinDelay, App::get().options().adjusterMaxDelay), -+ sliderChange(App::get().options().adjusterMinDelay, App::get().options().adjusterMaxDelay), - editedCheckBox(nullptr), - afterReset(false), - blocked(false), -diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc -index a62d150f0..0396bd07a 100644 ---- a/rtgui/batchqueue.cc -+++ b/rtgui/batchqueue.cc -@@ -56,7 +56,7 @@ namespace // local helper functions - // For N, return Nth index from the end, and for -N return the Nth index from the start. - // N is a digit 1 through 9. The returned value is not range-checked, so it may be >=numPathElements. - // or negative. The caller performs any required range-checking. -- int decodePathIndex(unsigned int& ix, Glib::ustring& templateText, size_t numPathElements) -+ int decodePathIndex(unsigned int& ix, const Glib::ustring& templateText, size_t numPathElements) - { - int pathIndex = static_cast(numPathElements); // a value that means input was invalid - bool fromStart = false; -@@ -196,7 +196,7 @@ void BatchQueue::resizeLoadedQueue() - // leading to very long waiting when adding more images - int BatchQueue::calcMaxThumbnailHeight() - { -- return std::min(options.maxThumbnailHeight, 200); -+ return std::min(App::get().options().maxThumbnailHeight, 200); - } - - // Function for virtual override in thumbbrowser base -@@ -207,13 +207,13 @@ int BatchQueue::getMaxThumbnailHeight() const - - void BatchQueue::saveThumbnailHeight (int height) - { -- options.thumbSizeQueue = height; -+ App::get().mut_options().thumbSizeQueue = height; - } - - int BatchQueue::getThumbnailHeight () - { - // The user could have manually forced the option to a too big value -- return std::max(std::min(options.thumbSizeQueue, 200), 10); -+ return std::max(std::min(App::get().options().thumbSizeQueue, 200), 10); - } - - void BatchQueue::rightClicked () -@@ -297,7 +297,7 @@ void BatchQueue::addEntries (const std::vector& entries, bool - - bool BatchQueue::saveBatchQueue () - { -- const auto fileName = Glib::build_filename (options.rtdir, "batch", "queue.csv"); -+ const auto fileName = Glib::build_filename (App::get().options().rtdir, "batch", "queue.csv"); - - std::ofstream file (fileName, std::ios::binary | std::ios::trunc); - -@@ -343,6 +343,7 @@ bool BatchQueue::saveBatchQueue () - - bool BatchQueue::loadBatchQueue () - { -+ const auto& options = App::get().options(); - const auto fileName = Glib::build_filename (options.rtdir, "batch", "queue.csv"); - - std::ifstream file (fileName, std::ios::binary); -@@ -471,12 +472,12 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring &filenam - timeinfo = localtime ( &rawtime ); - strftime (stringTimestamp, sizeof(stringTimestamp), "_%Y%m%d%H%M%S_", timeinfo); - Glib::ustring savedParamPath; -- savedParamPath = options.rtdir + "/batch/"; -+ savedParamPath = App::get().options().rtdir + "/batch/"; - g_mkdir_with_parents (savedParamPath.c_str (), 0755); - savedParamPath += Glib::path_get_basename (filename); - savedParamPath += stringTimestamp; - savedParamPath += mseconds; -- savedParamPath += paramFileExtension; -+ savedParamPath += App::PARAM_FILE_EXTENSION; - return savedParamPath; - } - -@@ -643,6 +644,7 @@ void BatchQueue::updateDestinationPathPreview() - if (!selected.empty()) { - auto& entry = *selected.at(0); - int sequence = 0; // Sequence during subsequent queue processing can't be determined here -+ const auto& options = App::get().options(); - Glib::ustring baseDestination = calcAutoFileNameBase(entry.filename, sequence); - Glib::ustring destination = Glib::ustring::compose ("%1.%2", baseDestination, options.saveFormatBatch.format); - -@@ -758,6 +760,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) - Glib::ustring fname; - SaveFormat saveFormat; - -+ const auto& options = App::get().options(); - if (processing->outFileName.empty()) { // auto file name - Glib::ustring s = calcAutoFileNameBase (processing->filename, processing->sequence); - saveFormat = options.saveFormatBatch; -@@ -803,8 +806,8 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) - if (saveFormat.saveParams) { - // We keep the extension to avoid overwriting the profile when we have - // the same output filename with different extension -- //processing->params.save (removeExtension(fname) + paramFileExtension); -- processing->params->save (fname + ".out" + paramFileExtension); -+ //processing->params.save (removeExtension(fname) + App::PARAM_FILE_EXTENSION); -+ processing->params->save (fname + ".out" + App::PARAM_FILE_EXTENSION); - } - - if (processing->thumbnail) { -@@ -932,6 +935,8 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam - filename = origFileName[k] + filename; - } - -+ const auto& options = App::get().options(); -+ - // printf ("%d, |%s|\n", extpos, filename.c_str()); - - // constructing full output path -@@ -994,7 +999,7 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam - char rank; - rtengine::procparams::ProcParams pparams; - -- if( pparams.load(origFileName + paramFileExtension) == 0 ) { -+ if( pparams.load(origFileName + App::PARAM_FILE_EXTENSION) == 0 ) { - if (!pparams.inTrash) { - rank = pparams.rank + '0'; - } else { -diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc -index 81f7176b3..3057407b3 100644 ---- a/rtgui/batchqueueentry.cc -+++ b/rtgui/batchqueueentry.cc -@@ -108,6 +108,7 @@ void BatchQueueEntry::refreshThumbnailImage () - void BatchQueueEntry::calcThumbnailSize () - { - prew = preh * origpw / origph; -+ const auto& options = App::get().options(); - if (prew > options.maxThumbnailWidth) { - const float s = static_cast(options.maxThumbnailWidth) / prew; - prew = options.maxThumbnailWidth; -diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc -index b477790fc..529f03fa1 100644 ---- a/rtgui/batchqueuepanel.cc -+++ b/rtgui/batchqueuepanel.cc -@@ -42,6 +42,8 @@ static Glib::ustring makeFolderLabel(Glib::ustring path) - - BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) : parent(nullptr) - { -+ const auto& options = App::get().options(); -+ - set_orientation(Gtk::ORIENTATION_VERTICAL); - batchQueue = Gtk::manage( new BatchQueue(aFileCatalog) ); - -@@ -215,7 +217,7 @@ void BatchQueuePanel::init (RTWindow *parent) - { - this->parent = parent; - -- saveFormatPanel->init (options.saveFormatBatch); -+ saveFormatPanel->init (App::get().options().saveFormatBatch); - } - - // it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ignored and computed automatically -@@ -228,7 +230,7 @@ void BatchQueuePanel::updateTab (int qsize, int forceOrientation) - } - - Gtk::Grid* grid = Gtk::manage (new Gtk::Grid ()); -- if ((forceOrientation == 0 && options.mainNBVertical) || (forceOrientation == 2)) { -+ if ((forceOrientation == 0 && App::get().options().mainNBVertical) || (forceOrientation == 2)) { - Gtk::Label* l; - - if(!qsize ) { -@@ -279,7 +281,7 @@ void BatchQueuePanel::queueSizeChanged(int qsize, bool queueRunning, bool queueE - // There was work, but it is all done now. - queueShouldRun = false; - -- SoundManager::playSoundAsync(options.sndBatchQueueDone); -+ SoundManager::playSoundAsync(App::get().options().sndBatchQueueDone); - } - - if (queueError) { -@@ -353,6 +355,8 @@ void BatchQueuePanel::templateHelpButtonToggled() - - void BatchQueuePanel::populateTemplateHelpBuffer(Glib::RefPtr buffer) - { -+ auto& options = App::get().mut_options(); -+ - auto pos = buffer->begin(); - const auto insertTopicHeading = [&pos, buffer](const Glib::ustring& text) { - pos = buffer->insert_markup(pos, Glib::ustring::format("\n\n", text, "\n")); -@@ -403,6 +407,7 @@ void BatchQueuePanel::populateTemplateHelpBuffer(Glib::RefPtr b - // number of elements in the path. - const auto insertPathExamples = [&buffer, &pos, pathElementCount, exampleFilePath](char letter, int offset1, int mult1, int offset2, int mult2) - { -+ auto& options = App::get().mut_options(); - for (int n=0; n& ent - - void BatchQueuePanel::saveOptions () - { -+ auto& options = App::get().mut_options(); - - options.savePathTemplate = outdirTemplate->get_text(); - options.saveUsePathTemplate = useTemplate->get_active(); -@@ -506,6 +512,7 @@ void BatchQueuePanel::setDestinationPreviewText(const Glib::ustring &destination - - void BatchQueuePanel::pathFolderButtonPressed () - { -+ auto& options = App::get().mut_options(); - - Gtk::FileChooserDialog fc (getToplevelWindow (this), M("QUEUE_LOCATION_FOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); - fc.add_button( "_Cancel", Gtk::RESPONSE_CANCEL); // STOCKICON WAS THERE -@@ -526,12 +533,14 @@ void BatchQueuePanel::pathFolderButtonPressed () - // since these settings are shared with editorpanel : - void BatchQueuePanel::pathFolderChanged () - { -+ auto& options = App::get().mut_options(); - options.savePathFolder = outdirFolder->get_filename(); - batchQueue->updateDestinationPathPreview(); - } - - void BatchQueuePanel::formatChanged(const Glib::ustring& format) - { -+ auto& options = App::get().mut_options(); - options.saveFormatBatch = saveFormatPanel->getFormat(); - batchQueue->updateDestinationPathPreview(); - } -diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc -index 4b6e16dca..426c8a6ee 100644 ---- a/rtgui/batchtoolpanelcoord.cc -+++ b/rtgui/batchtoolpanelcoord.cc -@@ -184,6 +184,7 @@ void BatchToolPanelCoordinator::initSession () - bayerrawexposure->setAdjusterBehavior (false); - xtransrawexposure->setAdjusterBehavior (false); - } else { -+ const Options& options = App::get().options(); - - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels.at (i)->setMultiImage (true); -@@ -757,6 +758,7 @@ void BatchToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) - - // toolBar->setTool (TOOL_HAND); - if (x > 0 && y > 0 && thm) { -+ const auto& options = App::get().options(); - for (size_t i = 0; i < selected.size(); i++) - if (selected[i] == thm) { - double temp; -diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc -index ac2faf58f..d23554a13 100644 ---- a/rtgui/bayerpreprocess.cc -+++ b/rtgui/bayerpreprocess.cc -@@ -30,8 +30,9 @@ using namespace rtengine::procparams; - - const Glib::ustring BayerPreProcess::TOOL_NAME = "bayerpreprocess"; - --BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) -+BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), App::get().options().prevdemo != PD_Sidecar) - { -+ const auto& options = App::get().options(); - auto m = ProcEventMapper::getInstance(); - EvLineDenoiseDirection = m->newEvent(DARKFRAME, "HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION"); - EvPDAFLinesFilter = m->newEvent(DARKFRAME, "HISTORY_MSG_PREPROCESS_PDAFLINESFILTER"); -diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc -index 4d5d0fa5c..9cdd30b77 100644 ---- a/rtgui/bayerprocess.cc -+++ b/rtgui/bayerprocess.cc -@@ -31,9 +31,10 @@ using namespace rtengine::procparams; - const Glib::ustring BayerProcess::TOOL_NAME = "bayerprocess"; - - BayerProcess::BayerProcess () : -- FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar), -+ FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), App::get().options().prevdemo != PD_Sidecar), - oldMethod(-1) - { -+ const auto& options = App::get().options(); - - auto m = ProcEventMapper::getInstance(); - EvDemosaicBorder = m->newEvent(DARKFRAME, "HISTORY_MSG_RAW_BORDER"); -diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc -index db6ceea41..fd37142d5 100644 ---- a/rtgui/bayerrawexposure.cc -+++ b/rtgui/bayerrawexposure.cc -@@ -28,8 +28,9 @@ using namespace rtengine::procparams; - - const Glib::ustring BayerRAWExposure::TOOL_NAME = "bayerrawexposure"; - --BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL"), options.prevdemo != PD_Sidecar) -+BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL"), App::get().options().prevdemo != PD_Sidecar) - { -+ const auto& options = App::get().options(); - auto m = ProcEventMapper::getInstance(); - EvDehablack = m->newEvent(DARKFRAME, "HISTORY_MSG_DEHABLACK"); - EvDehablackVoid = m->newEvent(M_VOID, "HISTORY_MSG_DEHABLACK"); -diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc -index f67ee9b7f..15d8131ca 100644 ---- a/rtgui/blackwhite.cc -+++ b/rtgui/blackwhite.cc -@@ -77,6 +77,7 @@ BlackWhite::BlackWhite (): FoldableToolPanel(this, TOOL_NAME, M("TP_BWMIX_LABEL" - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - -+ auto& options = App::get().mut_options(); - luminanceCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CHANNEL")); - luminanceCEG->setCurveListener (this); - luminanceCurve = static_cast(luminanceCEG->addCurve(CT_Flat, M("TP_BWMIX_VAL"))); -diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc -index e0b887eaa..107bfa3d4 100644 ---- a/rtgui/bqentryupdater.cc -+++ b/rtgui/bqentryupdater.cc -@@ -28,6 +28,7 @@ namespace - - void thumbInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) - { -+ const auto& options = App::get().options(); - - if (options.thumbInterp == 0) { - rtengine::nearestInterp (src, sw, sh, dst, dw, dh); -diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc -index 7804b69b4..1e841ea0b 100644 ---- a/rtgui/cachemanager.cc -+++ b/rtgui/cachemanager.cc -@@ -54,7 +54,7 @@ void CacheManager::init () - MyMutex::MyLock lock (mutex); - - openEntries.clear (); -- baseDir = options.cacheBaseDir; -+ baseDir = App::get().options().cacheBaseDir; - - auto error = g_mkdir_with_parents (baseDir.c_str(), cacheDirMode); - -@@ -198,7 +198,7 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin - - const auto newmd5 = getMD5 (newfilename); - -- auto error = g_rename (getCacheFileName ("profiles", oldfilename, paramFileExtension, oldmd5).c_str (), getCacheFileName ("profiles", newfilename, paramFileExtension, newmd5).c_str ()); -+ auto error = g_rename (getCacheFileName ("profiles", oldfilename, App::PARAM_FILE_EXTENSION, oldmd5).c_str (), getCacheFileName ("profiles", newfilename, App::PARAM_FILE_EXTENSION, newmd5).c_str ()); - error |= g_rename (getCacheFileName ("images", oldfilename, ".rtti", oldmd5).c_str (), getCacheFileName ("images", newfilename, ".rtti", newmd5).c_str ()); - error |= g_rename (getCacheFileName ("embprofiles", oldfilename, ".icc", oldmd5).c_str (), getCacheFileName ("embprofiles", newfilename, ".icc", newmd5).c_str ()); - error |= g_rename (getCacheFileName ("data", oldfilename, ".txt", oldmd5).c_str (), getCacheFileName ("data", newfilename, ".txt", newmd5).c_str ()); -@@ -299,7 +299,7 @@ void CacheManager::deleteFiles (const Glib::ustring& fname, const std::string& m - } - - if (purgeProfile) { -- error |= g_remove (getCacheFileName ("profiles", fname, paramFileExtension, md5).c_str ()); -+ error |= g_remove (getCacheFileName ("profiles", fname, App::PARAM_FILE_EXTENSION, md5).c_str ()); - } - - if (error != 0 && rtengine::settings->verbose) { -@@ -371,6 +371,7 @@ void CacheManager::applyCacheSizeLimitation () const - numFiles -= 2; // because . and .. are counted - } - -+ const auto& options = App::get().options(); - if (numFiles <= options.maxCacheEntries) { - return; - } -diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc -index 4e371db40..60cf5f810 100644 ---- a/rtgui/colorappearance.cc -+++ b/rtgui/colorappearance.cc -@@ -216,6 +216,8 @@ static double wbTemp2Slider (double temp) - - ColorAppearance::ColorAppearance () : FoldableToolPanel (this, TOOL_NAME, M ("TP_COLORAPP_LABEL"), false, true) - { -+ auto& options = App::get().mut_options(); -+ - CurveListener::setMulti (true); - std::vector milestones; - milestones.push_back ( GradientMilestone (0., 0., 0., 0.) ); -diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc -index 585d900eb..432ad9496 100644 ---- a/rtgui/colortoning.cc -+++ b/rtgui/colortoning.cc -@@ -65,6 +65,8 @@ ColorToning::ColorToning () : FoldableToolPanel(this, TOOL_NAME, M("TP_COLORTONI - colorSep = Gtk::manage (new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL)); - pack_start (*colorSep); - -+ auto& options = App::get().mut_options(); -+ - colorCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_COLOR")); - colorCurveEditorG->setCurveListener (this); - -diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc -index c301fb3df..63153f8b0 100644 ---- a/rtgui/controlspotpanel.cc -+++ b/rtgui/controlspotpanel.cc -@@ -29,8 +29,6 @@ - using namespace rtengine; - using namespace procparams; - --extern Options options; -- - //----------------------------------------------------------------------------- - // ControlSpotPanel - //----------------------------------------------------------------------------- -@@ -120,7 +118,7 @@ ControlSpotPanel::ControlSpotPanel(): - auto m = ProcEventMapper::getInstance(); - EvLocallabavoidgamutMethod = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_GAMUTMUNSEL"); - EvLocallabavoidnegative = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_AVOIDNEGATIVE"); -- const bool showtooltip = options.showtooltip; -+ const bool showtooltip = App::get().options().showtooltip; - - // pack_start(*hishow_); - -@@ -2922,7 +2920,7 @@ void ControlSpotPanel::updateguiset(int spottype, bool iscolor, bool issh, bool - - // Update GUI fullimage or main - disableListener(); -- if(spottype >= 2 && options.spotmet >= 2) {//optimize update -+ if(spottype >= 2 && App::get().options().spotmet >= 2) {//optimize update - spotMethodChanged(); - } - -diff --git a/rtgui/crop.cc b/rtgui/crop.cc -index 34f279e80..50bef963d 100644 ---- a/rtgui/crop.cc -+++ b/rtgui/crop.cc -@@ -335,7 +335,7 @@ Crop::~Crop() - void Crop::writeOptions () - { - -- options.cropPPI = (int)ppi->get_value (); -+ App::get().mut_options().cropPPI = (int)ppi->get_value (); - } - - void Crop::readOptions () -@@ -343,7 +343,7 @@ void Crop::readOptions () - - disableListener (); - -- ppi->set_value (options.cropPPI); -+ ppi->set_value (App::get().options().cropPPI); - - enableListener (); - } -diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc -index 131851372..3bd899d30 100644 ---- a/rtgui/cropwindow.cc -+++ b/rtgui/cropwindow.cc -@@ -79,7 +79,7 @@ Glib::ustring CropWindow::closett; - CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow) - : ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false), - fitZoomEnabled(true), fitZoom(false), cursor_type(CSArrow), /*isLowUpdatePriority(isLowUpdatePriority_),*/ hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")), -- backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), -+ backColor(App::get().options().bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), - upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0), - imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(nullptr), - pmlistener(nullptr), pmhlistener(nullptr), scrollAccum(0.0), observedCropWin(nullptr), -@@ -382,7 +382,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) - screenCoordToImage (x, y, action_x, action_y); - changeZoom (zoom11index, true, action_x, action_y); - fitZoom = false; -- } else if (options.cropAutoFit) { -+ } else if (App::get().options().cropAutoFit) { - zoomFitCrop(); - } else { - zoomFit(); -@@ -685,6 +685,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) - - void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) - { -+ auto& options = App::get().mut_options(); - - EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - -@@ -891,6 +892,7 @@ void CropWindow::pointerMoved (int bstate, int x, int y) - - iarea->redraw (); - } else if (state == SCropImgMove) { -+ const auto& options = App::get().options(); - // multiplier is the amplification factor ; disabled if the user selected "1" (no amplification) - double factor = options.panAccelFactor == 1 ? 1.0 : options.panAccelFactor * zoomSteps[cropZoom].zoom; - -@@ -1449,6 +1451,8 @@ void CropWindow::expose (Cairo::RefPtr cr) - drawDecoration (cr); - } - -+ auto& options = App::get().mut_options(); -+ - int x = xpos, y = ypos; - - // draw the background -@@ -2251,7 +2255,7 @@ void CropWindow::zoomFitCrop () - centerY = cropHandler.cropParams->y + cropHandler.cropParams->h / 2; - setCropAnchorPosition(centerX, centerY); - changeZoom (cz, true, centerX, centerY); -- fitZoom = options.cropAutoFit; -+ fitZoom = App::get().options().cropAutoFit; - } else { - zoomFit(); - } -@@ -2320,7 +2324,7 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, bo - } - - // Limit zoom according to user preferences -- double zoomLimit = zoomLimitToFraction(options.maxZoomLimit); -+ double zoomLimit = zoomLimitToFraction(App::get().options().maxZoomLimit); - while(zoomSteps[zoom].zoom > zoomLimit && zoom != 0) { - --zoom; - } -@@ -2681,6 +2685,8 @@ void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, in - cr->rectangle (x - 0.5, y - 0.5, w + 4, h + 4); - cr->stroke (); - -+ const auto& options = App::get().options(); -+ - // draw a "frame" line. Color of frame line can be set in preferences - cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1, 1, 1, 1.0); - cr->rectangle (x - 1.5, y - 1.5, w + 4, h + 4); -diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc -index 5ce3765a2..dedff2565 100644 ---- a/rtgui/curveeditorgroup.cc -+++ b/rtgui/curveeditorgroup.cc -@@ -30,7 +30,7 @@ - #include "pathutils.h" - #include "rtscalable.h" - --CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel, int blank) : curveDir(curveDir), line(0), curve_reset(nullptr), -+CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, const Glib::ustring& groupLabel, int blank) : curveDir(curveDir), line(0), curve_reset(nullptr), - displayedCurve(nullptr), flatSubGroup(nullptr), diagonalSubGroup(nullptr), cl(nullptr), numberOfPackedCurve(0) - { - -@@ -426,6 +426,7 @@ CurveEditorSubGroup::~CurveEditorSubGroup() - - void CurveEditorSubGroup::initButton (Gtk::Button &button, const Glib::ustring &iconName, Gtk::Align align, bool separatorButton, const Glib::ustring &tooltip) - { -+ const auto& options = App::get().options(); - bool hExpand, vExpand; - if (separatorButton) { - hExpand = vExpand = true; -diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h -index aa9765926..bcc13273f 100644 ---- a/rtgui/curveeditorgroup.h -+++ b/rtgui/curveeditorgroup.h -@@ -71,7 +71,7 @@ public: - * dialogs. - */ - -- explicit CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = "", int blank = 0); -+ explicit CurveEditorGroup(Glib::ustring& curveDir, const Glib::ustring& groupLabel = "", int blank = 0); - ~CurveEditorGroup() override; - void newLine(); - void curveListComplete(); -diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc -index ec628da64..0151ec649 100644 ---- a/rtgui/darkframe.cc -+++ b/rtgui/darkframe.cc -@@ -37,6 +37,7 @@ DarkFrame::DarkFrame () : FoldableToolPanel(this, TOOL_NAME, M("TP_DARKFRAME_LAB - hbdf = Gtk::manage(new Gtk::Box()); - hbdf->set_spacing(4); - darkFrameFile = Gtk::manage(new MyFileChooserButton(M("TP_DARKFRAME_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); -+ auto& options = App::get().mut_options(); - bindCurrentFolder (*darkFrameFile, options.lastDarkframeDir); - dfLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); - btnReset = Gtk::manage(new Gtk::Button()); -@@ -211,6 +212,7 @@ void DarkFrame::darkFrameChanged() - void DarkFrame::darkFrameReset() - { - dfChanged = true; -+ const auto& options = App::get().options(); - - // caution: I had to make this hack, because set_current_folder() doesn't work correctly! - // Because szeva doesn't exist since he was committed to happy hunting ground in Issue 316 -diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc -index 162538db0..53190c72a 100644 ---- a/rtgui/defringe.cc -+++ b/rtgui/defringe.cc -@@ -44,6 +44,7 @@ Defringe::Defringe () : FoldableToolPanel(this, TOOL_NAME, M("TP_DEFRINGE_LABEL" - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - -+ auto& options = App::get().mut_options(); - curveEditorPF = new CurveEditorGroup (options.lastPFCurvesDir); - curveEditorPF->setCurveListener (this); - chshape = static_cast(curveEditorPF->addCurve(CT_Flat, M("TP_PFCURVE_CURVEEDITOR_CH"))); -diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc -index c30aa599a..209087737 100644 ---- a/rtgui/diagonalcurveeditorsubgroup.cc -+++ b/rtgui/diagonalcurveeditorsubgroup.cc -@@ -38,6 +38,7 @@ - - DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) - { -+ const auto& options = App::get().options(); - - editedAdjuster = nullptr; - editedAdjusterValue = 0; -diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc -index fdde48637..ce6112290 100644 ---- a/rtgui/dirbrowser.cc -+++ b/rtgui/dirbrowser.cc -@@ -144,6 +144,7 @@ void DirBrowser::fillDirTree () - - dirtree->append_column(tvc); - -+ const auto& options = App::get().options(); - tvc.set_sort_order(options.dirBrowserSortType); - tvc.set_sort_column(dtColumns.filename); - tvc.set_sort_indicator(true); -@@ -267,6 +268,7 @@ void DirBrowser::fillRoot () - - void DirBrowser::on_sort_column_changed() const - { -+ auto& options = App::get().mut_options(); - options.dirBrowserSortType = tvc.get_sort_order(); - } - -@@ -285,13 +287,14 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: - dirTreeModel->get_sort_column_id(prevSortColumn, prevSortType); - dirTreeModel->set_sort_column(Gtk::TreeSortable::DEFAULT_UNSORTED_COLUMN_ID, Gtk::SORT_ASCENDING); - -+ const auto& options = App::get().options(); - auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - auto subDirs = listSubDirs (dir, options.fbShowHidden); - - Gtk::TreeNodeChildren children = iter->children(); - std::list forErase(children.begin(), children.end()); - -- std::sort (subDirs.begin (), subDirs.end (), [] (const Glib::ustring& firstDir, const Glib::ustring& secondDir) -+ std::sort (subDirs.begin (), subDirs.end (), [&](const Glib::ustring& firstDir, const Glib::ustring& secondDir) - { - switch (options.dirBrowserSortType) { - default: -@@ -353,7 +356,7 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) - - // test if new files are created - auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); -- auto subDirs = listSubDirs (dir, options.fbShowHidden); -+ auto subDirs = listSubDirs (dir, App::get().options().fbShowHidden); - - for (size_t i = 0; i < subDirs.size(); i++) { - bool found = false; -diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc -index 629898d52..3616e7b40 100644 ---- a/rtgui/dirpyrdenoise.cc -+++ b/rtgui/dirpyrdenoise.cc -@@ -70,6 +70,7 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, TOOL_NAME, M("TP_DIRPY - - luma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING"), 0, 100, 0.01, 0)); - Ldetail = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMINANCE_DETAIL"), 0, 100, 0.01, 0)); -+ auto& options = App::get().mut_options(); - NoiscurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_LUMINANCE_CURVE")); - //curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); - NoiscurveEditorG->setCurveListener (this); -@@ -444,7 +445,7 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) - - LmethodChanged(); - -- if(options.rtSettings.leveldnautsimpl == 1) { -+ if(App::get().options().rtSettings.leveldnautsimpl == 1) { - Cmethod->set_active (0); - - if (pp->dirpyrDenoise.Cmethod == "MAN") { -@@ -690,7 +691,7 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) - pp->dirpyrDenoise.Lmethod = "SLI"; - } - -- if(options.rtSettings.leveldnautsimpl == 1) { -+ if(App::get().options().rtSettings.leveldnautsimpl == 1) { - if (Cmethod->get_active_row_number() == 0) { - pp->dirpyrDenoise.Cmethod = "MAN"; - } else if (Cmethod->get_active_row_number() == 1) { -diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc -index abe0a1ec6..4edd99cdb 100644 ---- a/rtgui/editorpanel.cc -+++ b/rtgui/editorpanel.cc -@@ -396,7 +396,7 @@ private: - if (find_default_monitor_profile (profileBox.get_root_window()->gobj(), defprof, defprofname)) { - profileBox.append (M ("MONITOR_PROFILE_SYSTEM") + " (" + defprofname + ")"); - -- if (options.rtSettings.autoMonitorProfile) { -+ if (App::get().options().rtSettings.autoMonitorProfile) { - rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName (defprof); - profileBox.set_active (1); - } else { -@@ -480,6 +480,7 @@ private: - ConnectionBlocker intentBlocker (intentConn); - - Glib::ustring profile; -+ const auto& options = App::get().options(); - - #if !defined(__APPLE__) // monitor profile not supported on apple - -@@ -645,6 +646,8 @@ public: - - void reset () - { -+ const auto& options = App::get().options(); -+ - ConnectionBlocker intentBlocker (intentConn); - #if !defined(__APPLE__) // monitor profile not supported on apple - ConnectionBlocker profileBlocker (profileConn); -@@ -785,6 +788,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) - iHistoryShow = new RTImage ("panel-to-right", Gtk::ICON_SIZE_LARGE_TOOLBAR); - iHistoryHide = new RTImage ("panel-to-left", Gtk::ICON_SIZE_LARGE_TOOLBAR); - -+ const auto& options = App::get().options(); - hidehp->set_relief (Gtk::RELIEF_NONE); - hidehp->set_active (options.showHistory); - hidehp->set_tooltip_markup (M ("MAIN_TOOLTIP_HIDEHP")); -@@ -797,7 +801,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) - - tbTopPanel_1 = nullptr; - -- if (!simpleEditor && filePanel) { -+ if (!App::get().isSimpleEditor() && filePanel) { - tbTopPanel_1 = new Gtk::ToggleButton (); - iTopPanel_1_Show = new RTImage ("panel-to-bottom", Gtk::ICON_SIZE_LARGE_TOOLBAR); - iTopPanel_1_Hide = new RTImage ("panel-to-top", Gtk::ICON_SIZE_LARGE_TOOLBAR); -@@ -942,7 +946,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) - - navPrev = navNext = navSync = nullptr; - -- if (!simpleEditor && !options.tabbedUI) { -+ if (!App::get().isSimpleEditor() && !options.tabbedUI) { - // Navigation buttons - Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("arrow2-left", Gtk::ICON_SIZE_LARGE_TOOLBAR)); - navPrevImage->set_padding (0, 0); -@@ -976,15 +980,15 @@ EditorPanel::EditorPanel (FilePanel* filePanel) - iops->attach_next_to (*progressLabel, Gtk::POS_LEFT, 1, 1); - iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1); - -- if (!gimpPlugin) { -+ if (!App::get().isGimpPlugin()) { - iops->attach_next_to(*send_to_external->buttonGroup, Gtk::POS_LEFT, 1, 1); - } - -- if (!gimpPlugin && !simpleEditor) { -+ if (!App::get().isGimpPlugin() && !App::get().isSimpleEditor()) { - iops->attach_next_to (*queueimg, Gtk::POS_LEFT, 1, 1); - } - -- if (!gimpPlugin) { -+ if (!App::get().isGimpPlugin()) { - iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); - } - -@@ -993,7 +997,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) - colorMgmtToolBar.reset (new ColorManagementToolbar (ipc)); - colorMgmtToolBar->pack_right_in (iops); - -- if (!simpleEditor && !options.tabbedUI) { -+ if (!App::get().isSimpleEditor() && !options.tabbedUI) { - Gtk::Separator* vsep3 = Gtk::manage (new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)); - iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1); - iops->attach_next_to (*navPrev, Gtk::POS_RIGHT, 1, 1); -@@ -1168,7 +1172,7 @@ void EditorPanel::leftPaneButtonReleased (GdkEventButton *event) - { - if (event->button == 1) { - // Button 1 released : it's a resize -- options.historyPanelWidth = hpanedl->get_position(); -+ App::get().mut_options().historyPanelWidth = hpanedl->get_position(); - } - - /*else if (event->button == 3) { -@@ -1181,7 +1185,7 @@ void EditorPanel::rightPaneButtonReleased (GdkEventButton *event) - int winW, winH; - parentWindow->get_size (winW, winH); - // Button 1 released : it's a resize -- options.toolPanelWidth = winW - hpanedr->get_position(); -+ App::get().mut_options().toolPanelWidth = winW - hpanedr->get_position(); - } - - /*else if (event->button == 3) { -@@ -1223,6 +1227,7 @@ void EditorPanel::showTopPanel (bool show) - - void EditorPanel::setAspect () - { -+ const auto& options = App::get().options(); - int winW, winH; - parentWindow->get_size (winW, winH); - hpanedl->set_position (options.historyPanelWidth); -@@ -1281,6 +1286,7 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) - // try to load the last saved parameters from the cache or from the paramfile file - ProcParams* ldprof = openThm->createProcParamsForUpdate (true, false); // will be freed by initProfile - -+ const auto& options = App::get().options(); - // initialize profile - Glib::ustring defProf = openThm->getType() == FT_Raw ? options.defProfRaw : options.defProfImg; - profilep->initProfile (defProf, ldprof); -@@ -1535,6 +1541,7 @@ void EditorPanel::refreshProcessingState (bool inProcessingP) - if (processingStartedTime != 0) { - time_t curTime = ::time (nullptr); - -+ const auto& options = App::get().options(); - if (::difftime (curTime, processingStartedTime) > options.sndLngEditProcDoneSecs) { - SoundManager::playSoundAsync (options.sndLngEditProcDone); - } -@@ -1641,6 +1648,7 @@ void EditorPanel::hideHistoryActivated () - hpanedl->pack1 (*leftbox, false, false); - } - -+ auto& options = App::get().mut_options(); - options.showHistory = hidehp->get_active(); - - if (options.showHistory) { -@@ -1697,6 +1705,7 @@ void EditorPanel::tbTopPanel_1_toggled () - - if (catalogPane) { // catalogPane does not exist in multitab mode - -+ auto& options = App::get().mut_options(); - if (tbTopPanel_1->get_active()) { - catalogPane->show(); - tbTopPanel_1->set_image (*iTopPanel_1_Hide); -@@ -1882,7 +1891,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - return true; - - case GDK_KEY_y: // synchronize filebrowser with image in Editor -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - fPanel->fileCatalog->selectImage (fname, false); - return true; - } -@@ -1890,7 +1899,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - break; // to avoid gcc complain - - case GDK_KEY_x: // clear filters and synchronize filebrowser with image in Editor -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - fPanel->fileCatalog->selectImage (fname, true); - return true; - } -@@ -1906,21 +1915,21 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - return true; - - case GDK_KEY_s: -- if (!gimpPlugin) { -+ if (!App::get().isGimpPlugin()) { - saveAsPressed(); - } - - return true; - - case GDK_KEY_b: -- if (!gimpPlugin && !simpleEditor) { -+ if (!App::get().isGimpPlugin() && !App::get().isSimpleEditor()) { - queueImgPressed(); - } - - return true; - - case GDK_KEY_e: -- if (!gimpPlugin) { -+ if (!App::get().isGimpPlugin()) { - sendToExternalPressed(); - } - -@@ -1962,7 +1971,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - if (shift) { - switch (event->keyval) { - case GDK_KEY_F3: // open Previous image from Editor's perspective -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - EditorPanel::openPreviousEditorImage(); - return true; - } -@@ -1970,7 +1979,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - break; // to avoid gcc complain - - case GDK_KEY_F4: // open next image from Editor's perspective -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - EditorPanel::openNextEditorImage(); - return true; - } -@@ -1987,7 +1996,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) - return true; - } - -- if (!simpleEditor && fPanel) { -+ if (!App::get().isSimpleEditor() && fPanel) { - if (fPanel->handleShortcutKey (event)) { - return true; - } -@@ -2060,7 +2069,7 @@ bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImagef - if (sf.saveParams) { - // We keep the extension to avoid overwriting the profile when we have - // the same output filename with different extension -- pparams.save (fname + ".out" + paramFileExtension); -+ pparams.save (fname + ".out" + App::PARAM_FILE_EXTENSION); - } - } else { - error (M ("MAIN_MSG_CANNOTSAVE"), fname); -@@ -2075,7 +2084,7 @@ bool EditorPanel::idle_imageSaved (ProgressConnector *pc, rtengine::IImagef - setProgressState (false); - - delete pc; -- SoundManager::playSoundAsync (options.sndBatchQueueDone); -+ SoundManager::playSoundAsync (App::get().options().sndBatchQueueDone); - isProcessing = false; - return false; - } -@@ -2091,7 +2100,7 @@ BatchQueueEntry* EditorPanel::createBatchQueueEntry () - isrc->getImageSource()->getFullSize (fullW, fullH, pparams.coarse.rotate == 90 || pparams.coarse.rotate == 270 ? TR_R90 : TR_NONE); - int prevh = BatchQueue::calcMaxThumbnailHeight(); - int prevw = int ((size_t)fullW * (size_t)prevh / (size_t)fullH); -- return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm, options.overwriteOutputFile); -+ return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm, App::get().options().overwriteOutputFile); - } - - -@@ -2108,6 +2117,7 @@ void EditorPanel::saveAsPressed () - SaveAsDialog* saveAsDialog; - auto toplevel = static_cast (get_toplevel ()); - -+ auto& options = App::get().mut_options(); - if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { - saveAsDialog = new SaveAsDialog (options.lastSaveAsPath, toplevel); - } else { -@@ -2218,7 +2228,7 @@ void EditorPanel::sendToExternal() - // develop image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); -- if (options.editor_bypass_output_profile) { -+ if (App::get().options().editor_bypass_output_profile) { - pparams.icm.outputProfile = rtengine::procparams::ColorManagementParams::NoProfileString; - } - -@@ -2241,6 +2251,7 @@ void EditorPanel::sendToExternal() - void EditorPanel::sendToExternalChanged(int) - { - int index = send_to_external->getSelected(); -+ auto& options = App::get().mut_options(); - if (index >= 0 && static_cast(index) == options.externalEditors.size()) { - index = -1; - } -@@ -2252,6 +2263,7 @@ void EditorPanel::sendToExternalChanged(int) - - void EditorPanel::sendToExternalPressed() - { -+ const auto& options = App::get().options(); - if (options.externalEditorIndex == -1) { - // "Other" external editor. Show app chooser dialog to let user pick. - RTAppChooserDialog *dialog = getAppChooserDialog(); -@@ -2279,7 +2291,7 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm - - int err = 0; - -- if (gimpPlugin) { -+ if (App::get().isGimpPlugin()) { - err = img->saveAsTIFF (filename, 32, true, true); - } else if (sf.format == "tif") { - err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed, sf.bigTiff); -@@ -2298,21 +2310,21 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm - - void EditorPanel::openPreviousEditorImage() - { -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_PREVIOUS); - } - } - - void EditorPanel::openNextEditorImage() - { -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_NEXT); - } - } - - void EditorPanel::syncFileBrowser() // synchronize filebrowser with image in Editor - { -- if (!simpleEditor && fPanel && !fname.empty()) { -+ if (!App::get().isSimpleEditor() && fPanel && !fname.empty()) { - fPanel->fileCatalog->selectImage (fname, false); - } - } -@@ -2336,6 +2348,7 @@ void EditorPanel::setExternalEditorChangedSignal(ExternalEditorChangedSignal *si - - void EditorPanel::histogramProfile_toggled() - { -+ auto& options = App::get().mut_options(); - options.rtSettings.HistogramWorking = toggleHistogramProfile->get_active(); - colorMgmtToolBar->updateHistogram(); - } -@@ -2346,6 +2359,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p - rtengine::IImagefloat* img = pc->returnValue(); - delete pc; - -+ const auto& options = App::get().options(); - if (img) { - // get file name base - Glib::ustring shortname = removeExtension(Glib::path_get_basename(fname)); -@@ -2477,6 +2491,7 @@ void EditorPanel::onAppChooserDialogResponse(int responseId) - - void EditorPanel::updateExternalEditorSelection() - { -+ const auto& options = App::get().options(); - int index = send_to_external->getSelected(); - if (index >= 0 && static_cast(index) == options.externalEditors.size()) { - index = -1; -@@ -2816,6 +2831,7 @@ void EditorPanel::updateTPVScrollbar (bool hide) - - void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) - { -+ const auto& options = App::get().options(); - - switch (newPosition) { - case 0: -diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc -index ce39f5d6f..f48199b03 100644 ---- a/rtgui/editwindow.cc -+++ b/rtgui/editwindow.cc -@@ -26,15 +26,13 @@ - #include - #include "threadutils.h" - --extern Glib::ustring argv0; -- - // Check if the system has more than one display and option is set - bool EditWindow::isMultiDisplayEnabled() - { - const auto screen = Gdk::Screen::get_default(); - - if (screen) { -- return options.multiDisplayMode > 0 && screen->get_display()->get_n_monitors() > 1; -+ return App::get().options().multiDisplayMode > 0 && screen->get_display()->get_n_monitors() > 1; - } else { - return false; // There is no default screen - } -@@ -70,6 +68,7 @@ EditWindow::EditWindow (RTWindow* p) - set_title_decorated(""); - set_modal(false); - set_resizable(true); -+ const auto& options = App::get().options(); - set_default_size(options.meowWidth, options.meowHeight); - - property_destroy_with_parent().set_value(false); -@@ -96,6 +95,7 @@ void EditWindow::restoreWindow() - - int meowMonitor = 0; // By default, set to main monitor - const auto display = get_screen()->get_display(); -+ const auto& options = App::get().options(); - - if (isMultiDisplayEnabled()) { - if (options.meowMonitor >= 0) { // Use display from last session if available -@@ -168,6 +168,7 @@ void EditWindow::on_realize () - - bool EditWindow::on_configure_event(GdkEventConfigure* event) - { -+ auto& options = App::get().mut_options(); - if (!options.meowMaximized && !isFullscreen && !isMinimized) { - get_position(options.meowX, options.meowY); - get_size(options.meowWidth, options.meowHeight); -@@ -178,6 +179,7 @@ bool EditWindow::on_configure_event(GdkEventConfigure* event) - - bool EditWindow::on_window_state_event(GdkEventWindowState* event) - { -+ auto& options = App::get().mut_options(); - // Retrieve RT window states - options.meowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; - isMinimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED; -@@ -346,6 +348,7 @@ void EditWindow::get_position(int& x, int& y) const - - void EditWindow::writeOptions() - { -+ auto& options = App::get().mut_options(); - if (is_visible()) { - if (isMultiDisplayEnabled()) { - // Retrieve window monitor ID -diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc -index 6e9c13fc8..8456c25aa 100644 ---- a/rtgui/exportpanel.cc -+++ b/rtgui/exportpanel.cc -@@ -169,6 +169,7 @@ ExportPanel::ExportPanel () : listener (nullptr), ornamentSurface(new RTSurface( - pack_start (*wbox, Gtk::PACK_SHRINK, 4); - pack_start (*hbox, Gtk::PACK_SHRINK, 4); - -+ const auto& options = App::get().options(); - MaxWidth->set_digits (0); - MaxWidth->set_width_chars (5); - MaxWidth->set_max_width_chars (5); -@@ -255,6 +256,7 @@ void ExportPanel::SaveSettingsAsDefault() - changed = true; \ - } \ - } while (false) -+ auto& options = App::get().mut_options(); - // Save fast export settings to options - FE_OPT_STORE_ (options.fastexport_bypass_sharpening, bypass_sharpening->get_active ()); - FE_OPT_STORE_ (options.fastexport_bypass_sharpenEdge, bypass_sharpenEdge->get_active ()); -@@ -318,6 +320,7 @@ void ExportPanel::SaveSettingsAsDefault() - - void ExportPanel::LoadDefaultSettings() - { -+ const auto& options = App::get().options(); - // Load fast export settings from options - bypass_sharpening->set_active (options.fastexport_bypass_sharpening ); - bypass_sharpenEdge->set_active (options.fastexport_bypass_sharpenEdge ); -diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc -index dc3cb61b4..8579062e4 100644 ---- a/rtgui/extprog.cc -+++ b/rtgui/extprog.cc -@@ -242,6 +242,7 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName) - { - #if defined _WIN32 - -+ const auto& options = App::get().options(); - auto executable = Glib::build_filename (options.gimpDir, "bin", "gimp-win-remote"); - auto success = ShellExecute( NULL, "open", executable.c_str(), fileName.c_str(), NULL, SW_SHOWNORMAL ); - -@@ -300,6 +301,7 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName) - - bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName) - { -+ const auto& options = App::get().options(); - #if defined _WIN32 - - const auto executable = Glib::build_filename(options.psDir, "Photoshop.exe"); -@@ -321,7 +323,7 @@ bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName) - bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName, const Glib::ustring* command) - { - if (!command) { -- command = &(options.customEditorProg); -+ command = &(App::get().options().customEditorProg); - } - - #if defined _WIN32 -diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc -index a1043d661..5035ad6e2 100644 ---- a/rtgui/filebrowser.cc -+++ b/rtgui/filebrowser.cc -@@ -51,7 +51,7 @@ const Glib::ustring* getOriginalExtension (const ThumbBrowserEntryBase* entry) - typedef std::vector ExtensionVector; - typedef ExtensionVector::const_iterator ExtensionIterator; - -- const ExtensionVector& originalExtensions = options.parsedExtensions; -+ const ExtensionVector& originalExtensions = App::get().options().parsedExtensions; - - // Extract extension from basename - const Glib::ustring basename = Glib::path_get_basename (entry->filename.lowercase()); -@@ -148,6 +148,7 @@ FileBrowser::FileBrowser () : - session_id_ = 0; - - ProfileStore::getInstance()->addListener(this); -+ const auto& options = App::get().options(); - - int p = 0; - pmenu = new Gtk::Menu (); -@@ -771,6 +772,8 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) - return; - } - -+ const auto& options = App::get().options(); -+ - for (size_t j = 0; j < mMenuExtProgs.size(); j++) { - if (m == amiExtProg[j]) { - const auto pAct = mMenuExtProgs[m->get_label()]; -@@ -869,7 +872,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) - if( !mselected.empty() ) { - rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc (getToplevelWindow (this), "Dark Frame", Gtk::FILE_CHOOSER_ACTION_OPEN ); -- bindCurrentFolder (fc, options.lastDarkframeDir); -+ bindCurrentFolder (fc, App::get().mut_options().lastDarkframeDir); - fc.add_button( M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); - fc.add_button( M("GENERAL_APPLY"), Gtk::RESPONSE_APPLY); - -@@ -913,7 +916,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) - rtengine::DFManager::getInstance().init( options.rtSettings.darkFramesPath ); - } else { - // Target directory creation failed, we clear the darkFramesPath setting -- options.rtSettings.darkFramesPath.clear(); -+ App::get().mut_options().rtSettings.darkFramesPath.clear(); - Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), escapeHtmlChars(options.rtSettings.darkFramesPath)) - + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); -@@ -945,7 +948,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) - if( !mselected.empty() ) { - rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc (getToplevelWindow (this), "Flat Field", Gtk::FILE_CHOOSER_ACTION_OPEN ); -- bindCurrentFolder (fc, options.lastFlatfieldDir); -+ bindCurrentFolder (fc, App::get().mut_options().lastFlatfieldDir); - fc.add_button( M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); - fc.add_button( M("GENERAL_APPLY"), Gtk::RESPONSE_APPLY); - -@@ -989,7 +992,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) - rtengine::ffm.init( options.rtSettings.flatFieldsPath ); - } else { - // Target directory creation failed, we clear the flatFieldsPath setting -- options.rtSettings.flatFieldsPath.clear(); -+ App::get().mut_options().rtSettings.flatFieldsPath.clear(); - Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), escapeHtmlChars(options.rtSettings.flatFieldsPath)) - + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); -@@ -1392,6 +1395,7 @@ bool FileBrowser::keyPressed (GdkEventKey* event) - - void FileBrowser::saveThumbnailHeight (int height) - { -+ auto& options = App::get().mut_options(); - if (!options.sameThumbSize && getLocation() == THLOC_EDITOR) { - options.thumbSizeTab = height; - } else { -@@ -1401,6 +1405,7 @@ void FileBrowser::saveThumbnailHeight (int height) - - int FileBrowser::getThumbnailHeight () - { -+ const auto& options = App::get().options(); - // The user could have manually forced the option to a too big value - if (!options.sameThumbSize && getLocation() == THLOC_EDITOR) { - return std::max(std::min(options.thumbSizeTab, 800), 10); -@@ -1412,6 +1417,7 @@ int FileBrowser::getThumbnailHeight () - void FileBrowser::enableTabMode(bool enable) - { - ThumbBrowserBase::enableTabMode(enable); -+ const auto& options = App::get().options(); - if (options.inspectorWindow) { - if (enable) { - inspect->remove_accelerator(pmenu->get_accel_group(), GDK_KEY_f, (Gdk::ModifierType)0); -@@ -1669,12 +1675,14 @@ void FileBrowser::fromTrashRequested (std::vector tbe) - - void FileBrowser::sortMethodRequested (int method) - { -+ auto& options = App::get().mut_options(); - options.sortMethod = Options::SortMethod(method); - resort (); - } - - void FileBrowser::sortOrderRequested (int order) - { -+ auto& options = App::get().mut_options(); - options.sortDescending = !!order; - resort (); - } -@@ -1800,7 +1808,7 @@ void FileBrowser::openNextImage() - { - MYWRITERLOCK(l, entryRW); - -- if (!fd.empty() && selected.size() > 0 && !options.tabbedUI) { -+ if (!fd.empty() && selected.size() > 0 && !App::get().options().tabbedUI) { - for (size_t i = 0; i < fd.size() - 1; i++) { - if (selected[0]->thumbnail->getFileName() == fd[i]->filename) { // located 1-st image in current selection - if (i < fd.size() && tbl) { -@@ -1863,7 +1871,7 @@ void FileBrowser::openPrevImage() - { - MYWRITERLOCK(l, entryRW); - -- if (!fd.empty() && selected.size() > 0 && !options.tabbedUI) { -+ if (!fd.empty() && selected.size() > 0 && !App::get().options().tabbedUI) { - for (size_t i = 1; i < fd.size(); i++) { - if (selected[0]->thumbnail->getFileName() == fd[i]->filename) { // located 1-st image in current selection - if (i > 0 && tbl) { -@@ -1926,7 +1934,7 @@ void FileBrowser::selectImage(const Glib::ustring& fname, bool doScroll) - { - MYWRITERLOCK(l, entryRW); - -- if (!fd.empty() && !options.tabbedUI) { -+ if (!fd.empty() && !App::get().options().tabbedUI) { - for (size_t i = 0; i < fd.size(); i++) { - if (fname == fd[i]->filename && !fd[i]->filtered) { - // matching file found for sync -@@ -2058,6 +2066,8 @@ void FileBrowser::updateProfileList() - - subMenuList[0] = Gtk::manage (new Gtk::Menu ()); // adding the root submenu - -+ const auto& options = App::get().options(); -+ - // iterate the profile store's profile list - for (size_t i = 0; i < profEntries->size(); i++) { - // create a new label for the current entry (be it a folder or file) -@@ -2149,7 +2159,7 @@ void FileBrowser::openRequested( std::vector mselected) - { - std::vector entries; - // in Single Editor Mode open only last selected image -- size_t openStart = options.tabbedUI ? 0 : ( mselected.size() > 0 ? mselected.size() - 1 : 0); -+ size_t openStart = App::get().options().tabbedUI ? 0 : ( mselected.size() > 0 ? mselected.size() - 1 : 0); - - for (size_t i = openStart; i < mselected.size(); i++) { - entries.push_back (mselected[i]->thumbnail); -diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc -index 85ec0fad3..bb672efda 100644 ---- a/rtgui/filebrowserentry.cc -+++ b/rtgui/filebrowserentry.cc -@@ -112,7 +112,7 @@ void FileBrowserEntry::refreshQuickThumbnailImage () - } - - // Only make a (slow) processed preview if the picture has been edited at all -- bool upgrade_to_processed = (!options.internalThumbIfUntouched || thumbnail->isPParamsValid()); -+ bool upgrade_to_processed = (!App::get().options().internalThumbIfUntouched || thumbnail->isPParamsValid()); - thumbImageUpdater->add(this, &updatepriority, upgrade_to_processed, false, this); - } - -@@ -176,7 +176,7 @@ void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) - drawCrop (c, prex, prey, prew, preh, 0, 0, scale, *cropParams, true, false); - } else { - rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop; -- switch (options.cropGuides) { -+ switch (App::get().options().cropGuides) { - case Options::CROP_GUIDE_NONE: - cparams.guide = rtengine::procparams::CropParams::Guide::NONE; - break; -@@ -296,7 +296,7 @@ bool FileBrowserEntry::motionNotify (int x, int y) - - Inspector* inspector = parent->getInspector(); - -- if (inspector && inspector->isActive() && (!parent->isInTabMode() || options.inspectorWindow)) { -+ if (inspector && inspector->isActive() && (!parent->isInTabMode() || App::get().options().inspectorWindow)) { - const rtengine::Coord2D coord(getPosInImgSpace(x, y)); - - if (coord.x != -1.) { -diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc -index ce22bbfd8..9d4acc624 100644 ---- a/rtgui/filecatalog.cc -+++ b/rtgui/filecatalog.cc -@@ -48,6 +48,83 @@ - - using namespace std; - -+namespace { -+ -+void getFilesRecursively( -+ const Glib::ustring &dir_path, -+ int max_depth, -+ int &dir_quota, -+ std::vector &file_names, -+ std::vector> *directories_explored) -+{ -+ const auto& options = App::get().options(); -+ try { -+ const auto dir = Gio::File::create_for_path(dir_path); -+ -+ static const auto enumerate_attrs = -+ std::string(G_FILE_ATTRIBUTE_STANDARD_NAME) + "," + -+ G_FILE_ATTRIBUTE_STANDARD_TYPE + "," + -+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN + "," + -+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET; -+ auto enumerator = dir->enumerate_children( -+ enumerate_attrs, -+ options.browseRecursiveFollowLinks -+ ? Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NONE -+ : Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NOFOLLOW_SYMLINKS); -+ -+ if (directories_explored) { -+ directories_explored->push_back(dir); -+ } -+ -+ while (true) { -+ try { -+ const auto file = enumerator->next_file(); -+ if (!file) { -+ break; -+ } -+ -+ if (!options.fbShowHidden && file->is_hidden()) { -+ continue; -+ } -+ -+ if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) { -+ if (max_depth > 0 && dir_quota > 0) { -+ const Glib::ustring child_dir_path = Glib::build_filename(dir_path, file->get_name()); -+ getFilesRecursively(child_dir_path, max_depth - 1, --dir_quota, file_names, directories_explored); -+ } -+ continue; -+ } -+ -+ const Glib::ustring fname = file->get_name(); -+ const auto lastdot = fname.find_last_of('.'); -+ -+ if (lastdot >= fname.length() - 1) { -+ continue; -+ } -+ -+ const auto& extensions = options.parsedExtensionsSet; -+ if (extensions.find(fname.substr(lastdot + 1).lowercase()) == extensions.end()) { -+ continue; -+ } -+ -+ file_names.emplace_back(Glib::build_filename(dir_path, fname)); -+ } catch (const Glib::Exception& exception) { -+ if (rtengine::settings->verbose) { -+ std::cerr << exception.what() << std::endl; -+ } -+ } -+ } -+ -+ } catch (const Glib::Exception& exception) { -+ if (rtengine::settings->verbose) { -+ std::cerr << "Failed to list directory \"" << dir_path << "\": " << exception.what() << std::endl; -+ } -+ } -+} -+ -+ -+} // namespace -+ - FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : - filepanel(filepanel), - selectedDirectoryId(1), -@@ -136,6 +213,8 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : - Query->signal_activate().connect (sigc::mem_fun(*this, &FileCatalog::executeQuery)); //respond to the Enter key - Query->signal_key_press_event().connect(sigc::mem_fun(*this, &FileCatalog::Query_key_pressed)); - -+ const auto& options = App::get().options(); -+ - // if NOT a single row toolbar - if (!options.FileBrowserToolbarSingleRow) { - hbToolBar1STB = Gtk::manage(new MyScrolledToolbar()); -@@ -521,6 +600,7 @@ bool FileCatalog::capture_event(GdkEventButton* event) - - void FileCatalog::exifInfoButtonToggled() - { -+ auto& options = App::get().mut_options(); - if (inTabMode) { - options.filmStripShowFileNames = exifInfo->get_active(); - } else { -@@ -577,78 +657,9 @@ void FileCatalog::closeDir () - - std::vector FileCatalog::getFileList(std::vector> *dirs_explored) - { -- - std::vector names; - -- const std::set& extensions = options.parsedExtensionsSet; -- -- static void (*getFilesRecursively)(const Glib::ustring &, int, int &, std::vector &, std::vector> *) = [](const Glib::ustring &dir_path, int max_depth, int &dir_quota, std::vector &file_names, std::vector> * directories_explored) { -- try { -- -- const auto dir = Gio::File::create_for_path(dir_path); -- -- static const auto enumerate_attrs = -- std::string(G_FILE_ATTRIBUTE_STANDARD_NAME) + "," + -- G_FILE_ATTRIBUTE_STANDARD_TYPE + "," + -- G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN + "," + -- G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET; -- auto enumerator = dir->enumerate_children( -- enumerate_attrs, -- options.browseRecursiveFollowLinks -- ? Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NONE -- : Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NOFOLLOW_SYMLINKS); -- -- if (directories_explored) { -- directories_explored->push_back(dir); -- } -- -- while (true) { -- try { -- const auto file = enumerator->next_file(); -- if (!file) { -- break; -- } -- -- if (!options.fbShowHidden && file->is_hidden()) { -- continue; -- } -- -- if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) { -- if (max_depth > 0 && dir_quota > 0) { -- const Glib::ustring child_dir_path = Glib::build_filename(dir_path, file->get_name()); -- getFilesRecursively(child_dir_path, max_depth - 1, --dir_quota, file_names, directories_explored); -- } -- continue; -- } -- -- const Glib::ustring fname = file->get_name(); -- const auto lastdot = fname.find_last_of('.'); -- -- if (lastdot >= fname.length() - 1) { -- continue; -- } -- -- if (extensions.find(fname.substr(lastdot + 1).lowercase()) == extensions.end()) { -- continue; -- } -- -- file_names.emplace_back(Glib::build_filename(dir_path, fname)); -- } catch (Glib::Exception& exception) { -- if (rtengine::settings->verbose) { -- std::cerr << exception.what() << std::endl; -- } -- } -- } -- -- } catch (Glib::Exception& exception) { -- -- if (rtengine::settings->verbose) { -- std::cerr << "Failed to list directory \"" << dir_path << "\": " << exception.what() << std::endl; -- } -- -- } -- }; -- -+ const auto& options = App::get().options(); - int dirs_left = options.browseRecursive ? options.browseRecursiveMaxDirs : 0; - getFilesRecursively(selectedDirectory, options.browseRecursiveDepth, dirs_left, names, dirs_explored); - -@@ -738,6 +749,7 @@ void FileCatalog::enableTabMode(bool enable) - { - inTabMode = enable; - -+ const auto& options = App::get().options(); - if (enable) { - if (options.showFilmStripToolBar) { - showToolBar(); -@@ -769,6 +781,7 @@ void FileCatalog::_refreshProgressBar () - if (!inTabMode && (!previewsToLoad || std::floor(100.f * previewsLoaded / previewsToLoad) != std::floor(100.f * (previewsLoaded - 1) / previewsToLoad))) { - GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - -+ const auto& options = App::get().options(); - if (!progressImage || !progressLabel) { - // create tab label once - Gtk::Notebook *nb = (Gtk::Notebook *)(filepanel->get_parent()); -@@ -981,7 +994,7 @@ void FileCatalog::_openImage(const std::vector& tmb) - for (size_t i = 0; i < tmb.size() && continueToLoad; i++) { - // Open the image here, and stop if in Single Editor mode, or if an image couldn't - // be opened, would it be because the file doesn't exist or because of lack of RAM -- if( !(listener->fileSelected (tmb[i])) && !options.tabbedUI ) { -+ if( !(listener->fileSelected (tmb[i])) && !App::get().options().tabbedUI ) { - continueToLoad = false; - } - -@@ -1039,17 +1052,18 @@ void FileCatalog::deleteRequested(const std::vector& tbe, boo - // delete from file system - ::g_remove (fname.c_str ()); - // delete paramfile if found -- ::g_remove ((fname + paramFileExtension).c_str ()); -- ::g_remove ((removeExtension(fname) + paramFileExtension).c_str ()); -+ ::g_remove ((fname + App::PARAM_FILE_EXTENSION).c_str ()); -+ ::g_remove ((removeExtension(fname) + App::PARAM_FILE_EXTENSION).c_str ()); - // delete .thm file - ::g_remove ((removeExtension(fname) + ".thm").c_str ()); - ::g_remove ((removeExtension(fname) + ".THM").c_str ()); - - if (inclBatchProcessed) { -+ const auto& options = App::get().options(); - Glib::ustring procfName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - ::g_remove (procfName.c_str ()); - -- Glib::ustring procfNameParamFile = Glib::ustring::compose ("%1.%2.out%3", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format, paramFileExtension); -+ Glib::ustring procfNameParamFile = Glib::ustring::compose ("%1.%2.out%3", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format, App::PARAM_FILE_EXTENSION); - ::g_remove (procfNameParamFile.c_str ()); - } - -@@ -1078,6 +1092,7 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b - Gtk::FileChooserDialog fc (getToplevelWindow (this), fc_title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); - fc.add_button( M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); - fc.add_button( M("GENERAL_OK"), Gtk::RESPONSE_OK); -+ auto& options = App::get().mut_options(); - if (!options.lastCopyMovePath.empty() && Glib::file_test(options.lastCopyMovePath, Glib::FILE_TEST_IS_DIR)) { - fc.set_current_folder(options.lastCopyMovePath); - } else { -@@ -1105,7 +1120,7 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b - - // construct destination File Paths - Glib::ustring dest_fPath = Glib::build_filename (options.lastCopyMovePath, fname); -- Glib::ustring dest_fPath_param = dest_fPath + paramFileExtension; -+ Glib::ustring dest_fPath_param = dest_fPath + App::PARAM_FILE_EXTENSION; - - if (moveRequested && (src_Dir == options.lastCopyMovePath)) { - continue; -@@ -1138,17 +1153,17 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b - - - // attempt to copy/move paramFile only if it exist next to the src -- Glib::RefPtr scr_param = Gio::File::create_for_path ( src_fPath + paramFileExtension ); -+ Glib::RefPtr scr_param = Gio::File::create_for_path ( src_fPath + App::PARAM_FILE_EXTENSION ); - -- if (Glib::file_test( src_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { -+ if (Glib::file_test( src_fPath + App::PARAM_FILE_EXTENSION, Glib::FILE_TEST_EXISTS)) { - Glib::RefPtr dest_param = Gio::File::create_for_path ( dest_fPath_param); - - // copy/move paramFile to destination - if (moveRequested) { -- if (Glib::file_test( dest_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { -+ if (Glib::file_test( dest_fPath + App::PARAM_FILE_EXTENSION, Glib::FILE_TEST_EXISTS)) { - // profile already got copied to destination from cache after cacheMgr->renameEntry - // delete source profile as cleanup -- ::g_remove ((src_fPath + paramFileExtension).c_str ()); -+ ::g_remove ((src_fPath + App::PARAM_FILE_EXTENSION).c_str ()); - } else { - scr_param->move(dest_param); - } -@@ -1163,7 +1178,7 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b - Glib::ustring dest_fname = Glib::ustring::compose("%1%2%3%4%5", fname_noExt, "_", i_copyindex, ".", fname_Ext); - // re-construct destination File Paths - dest_fPath = Glib::build_filename (options.lastCopyMovePath, dest_fname); -- dest_fPath_param = dest_fPath + paramFileExtension; -+ dest_fPath_param = dest_fPath + App::PARAM_FILE_EXTENSION; - i_copyindex++; - } - }//while -@@ -1187,6 +1202,8 @@ void FileCatalog::developRequested(const std::vector& tbe, bo - Thumbnail* th = fbe->thumbnail; - rtengine::procparams::ProcParams params = th->getProcParams(); - -+ const auto& options = App::get().options(); -+ - // if fast mode is selected, override (disable) params - // controlling time and resource consuming tasks - // and also those which effect is not pronounced after reducing the image size -@@ -1352,7 +1369,7 @@ void FileCatalog::renameRequested(const std::vector& tbe) - - if (::g_rename (ofname.c_str (), nfname.c_str ()) == 0) { - cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); -- ::g_remove((ofname + paramFileExtension).c_str ()); -+ ::g_remove((ofname + App::PARAM_FILE_EXTENSION).c_str ()); - reparseDirectory (); - } - } -@@ -1644,7 +1661,7 @@ void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick - - void FileCatalog::showRecursiveToggled() - { -- options.browseRecursive = bRecursive->get_active(); -+ App::get().mut_options().browseRecursive = bRecursive->get_active(); - reparseDirectory(); - } - -@@ -1791,7 +1808,7 @@ void FileCatalog::reparseDirectory () - fileNamesToDel.push_back(entry->filename); - fileNamesToRemove.push_back(entry->filename); - } -- else if (!options.browseRecursive && Glib::path_get_dirname(entry->filename) != selectedDirectory) { -+ else if (!App::get().options().browseRecursive && Glib::path_get_dirname(entry->filename) != selectedDirectory) { - fileNamesToRemove.push_back(entry->filename); - } - } -@@ -1830,7 +1847,7 @@ void FileCatalog::reparseDirectory () - void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) - { - -- if ((options.has_retained_extention(file->get_parse_name()) -+ if ((App::get().options().has_retained_extention(file->get_parse_name()) - && (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)) - || (event_type == Gio::FILE_MONITOR_EVENT_CREATED && Glib::file_test(file->get_path(), Glib::FileTest::FILE_TEST_IS_DIR)) - || (event_type == Gio::FILE_MONITOR_EVENT_DELETED && std::find_if(dirMonitors.cbegin(), dirMonitors.cend(), [&file](const FileMonitorInfo &monitor) { return monitor.filePath == file->get_path(); }) != dirMonitors.cend())) { -@@ -1873,7 +1890,7 @@ void FileCatalog::addAndOpenFile (const Glib::ustring& fname) - - const auto lastdot = info->get_name().find_last_of('.'); - if (lastdot != Glib::ustring::npos) { -- if (!options.is_extention_enabled(info->get_name().substr(lastdot + 1))) { -+ if (!App::get().options().is_extention_enabled(info->get_name().substr(lastdot + 1))) { - return; - } - } else { -@@ -2153,6 +2170,7 @@ void FileCatalog::tbLeftPanel_1_toggled () - { - removeIfThere (filepanel->dirpaned, filepanel->placespaned, false); - -+ auto& options = App::get().mut_options(); - if (tbLeftPanel_1->get_active()) { - filepanel->dirpaned->pack1 (*filepanel->placespaned, false, true); - tbLeftPanel_1->set_image (*iLeftPanel_1_Hide); -@@ -2165,6 +2183,7 @@ void FileCatalog::tbLeftPanel_1_toggled () - - void FileCatalog::tbRightPanel_1_toggled () - { -+ auto& options = App::get().mut_options(); - if (tbRightPanel_1->get_active()) { - filepanel->rightBox->show(); - tbRightPanel_1->set_image (*iRightPanel_1_Hide); -@@ -2507,6 +2526,7 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) - } - } - -+ auto& options = App::get().mut_options(); - if (!ctrl || (alt && !options.tabbedUI)) { - switch(event->keyval) { - -diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc -index 1032b45e1..f069f099e 100644 ---- a/rtgui/filepanel.cc -+++ b/rtgui/filepanel.cc -@@ -32,6 +32,7 @@ - - FilePanel::FilePanel () : parent(nullptr), error(0) - { -+ const auto& options = App::get().options(); - - // Contains everything except for the batch Tool Panel and tabs (Fast Export, Inspect, etc) - dirpaned = Gtk::manage ( new Gtk::Paned () ); -@@ -186,6 +187,7 @@ void FilePanel::setAspect () - { - int winW, winH; - parent->get_size(winW, winH); -+ const auto& options = App::get().options(); - placespaned->set_position(options.dirBrowserHeight); - dirpaned->set_position(options.dirBrowserWidth); - tpcPaned->set_position(options.browserToolPanelHeight); -@@ -206,17 +208,18 @@ void FilePanel::init () - dirBrowser->fillDirTree (); - placesBrowser->refreshPlacesList (); - -- if (!argv1.empty() && Glib::file_test (argv1, Glib::FILE_TEST_EXISTS)) { -- Glib::ustring d(argv1); -+ if (!App::get().argv0().empty() && Glib::file_test (App::get().argv1(), Glib::FILE_TEST_EXISTS)) { -+ Glib::ustring d(App::get().argv1()); - if (!Glib::file_test(d, Glib::FILE_TEST_IS_DIR)) { - d = Glib::path_get_dirname(d); - } - dirBrowser->open(d); - } else { -+ const auto& options = App::get().options(); - if (options.startupDir == STARTUPDIR_HOME) { - dirBrowser->open (PlacesBrowser::userPicturesDir ()); - } else if (options.startupDir == STARTUPDIR_CURRENT) { -- dirBrowser->open (argv0); -+ dirBrowser->open (App::get().argv0()); - } else if (options.startupDir == STARTUPDIR_CUSTOM || options.startupDir == STARTUPDIR_LAST) { - if (options.startupPath.length() && Glib::file_test(options.startupPath, Glib::FILE_TEST_EXISTS) && Glib::file_test(options.startupPath, Glib::FILE_TEST_IS_DIR)) { - dirBrowser->open (options.startupPath); -@@ -246,7 +249,7 @@ bool FilePanel::fileSelected (Thumbnail* thm) - } - - // Check if it's already open BEFORE loading the file -- if (options.tabbedUI && parent->selectEditorPanel(thm->getFileName())) { -+ if (App::get().options().tabbedUI && parent->selectEditorPanel(thm->getFileName())) { - return true; - } - -@@ -294,6 +297,8 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector 0 && pendingLoads.front()->complete) { - pendingLoad *pl = pendingLoads.front(); -@@ -363,6 +368,7 @@ MAXGDIHANDLESREACHED: - - void FilePanel::saveOptions () - { -+ auto& options = App::get().mut_options(); - - int winW, winH; - parent->get_size(winW, winH); -diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc -index 73b940da2..fd2fd24cc 100644 ---- a/rtgui/filmnegative.cc -+++ b/rtgui/filmnegative.cc -@@ -55,6 +55,7 @@ Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring - adj->setAdjusterListener(listener); - adj->setLogScale(6, 1, true); - -+ const auto& options = App::get().options(); - adj->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - adj->show(); -@@ -68,6 +69,7 @@ Adjuster* createLevelAdjuster(AdjusterListener* listener, const Glib::ustring& l - adj->setAdjusterListener(listener); - // adj->setLogScale(6, 1000.0, true); - -+ const auto& options = App::get().options(); - adj->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - adj->show(); -@@ -82,6 +84,7 @@ Adjuster* createBalanceAdjuster(AdjusterListener* listener, const Glib::ustring& - adj->setAdjusterListener(listener); - adj->setLogScale(9, 0, true); - -+ const auto& options = App::get().options(); - adj->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - adj->show(); -diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc -index a4a7e9bb7..769d55da6 100644 ---- a/rtgui/filmsimulation.cc -+++ b/rtgui/filmsimulation.cc -@@ -65,7 +65,7 @@ bool notifySlowParseDir (const std::chrono::system_clock::time_point& startedAt) - FilmSimulation::FilmSimulation() - : FoldableToolPanel( this, TOOL_NAME, M("TP_FILMSIMULATION_LABEL"), false, true ) - { -- m_clutComboBox = Gtk::manage( new ClutComboBox(options.clutsDir) ); -+ m_clutComboBox = Gtk::manage( new ClutComboBox(App::get().options().clutsDir) ); - - int foundClutsCount = m_clutComboBox->foundClutsCount(); - -@@ -132,6 +132,7 @@ void FilmSimulation::read( const rtengine::procparams::ProcParams* pp, const Par - - setEnabled(pp->filmSimulation.enabled); - -+ const auto& options = App::get().options(); - if (!pp->filmSimulation.clutFilename.empty()) { - m_clutComboBox->setSelectedClut( - !Glib::path_is_absolute(pp->filmSimulation.clutFilename) -@@ -185,7 +186,7 @@ void FilmSimulation::write( rtengine::procparams::ProcParams* pp, ParamsEdited* - const Glib::ustring clutFName = m_clutComboBox->getSelectedClut(); - - if (clutFName != "NULL") { // We do not want to set "NULL" in clutFilename, even if "unedited" -- pp->filmSimulation.clutFilename = stripPrefixDir(clutFName, options.clutsDir); -+ pp->filmSimulation.clutFilename = stripPrefixDir(clutFName, App::get().options().clutsDir); - } - - pp->filmSimulation.strength = m_strength->getValue(); -@@ -214,6 +215,7 @@ ClutComboBox::ClutComboBox(const Glib::ustring &path): - if (!cm) { - cm.reset(new ClutModel(path)); - } -+ const auto& options = App::get().options(); - if (!cm2 && options.multiDisplayMode) { - cm2.reset(new ClutModel(path)); - } -@@ -236,7 +238,7 @@ ClutComboBox::ClutComboBox(const Glib::ustring &path): - - inline Glib::RefPtr &ClutComboBox::m_model() - { -- if (!batchMode || !options.multiDisplayMode) { -+ if (!batchMode || !App::get().options().multiDisplayMode) { - return cm->m_model; - } else { - return cm2->m_model; -@@ -246,7 +248,7 @@ inline Glib::RefPtr &ClutComboBox::m_model() - - inline ClutComboBox::ClutColumns &ClutComboBox::m_columns() - { -- if (!batchMode || !options.multiDisplayMode) { -+ if (!batchMode || !App::get().options().multiDisplayMode) { - return cm->m_columns; - } else { - return cm2->m_columns; -diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc -index afd9d8bd6..fbfecb6d0 100644 ---- a/rtgui/flatcurveeditorsubgroup.cc -+++ b/rtgui/flatcurveeditorsubgroup.cc -@@ -44,6 +44,7 @@ FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt, Glib::u - valUnchanged = (int)FCT_Unchanged; - parent = prt; - -+ const auto& options = App::get().options(); - Gtk::PositionType sideStart = options.curvebboxpos == 0 || options.curvebboxpos == 2 ? Gtk::POS_LEFT : Gtk::POS_TOP; - Gtk::PositionType sideEnd = options.curvebboxpos == 0 || options.curvebboxpos == 2 ? Gtk::POS_RIGHT : Gtk::POS_BOTTOM; - -diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc -index d12e39730..db94573d8 100644 ---- a/rtgui/flatfield.cc -+++ b/rtgui/flatfield.cc -@@ -38,6 +38,8 @@ FlatField::FlatField () : FoldableToolPanel(this, TOOL_NAME, M("TP_FLATFIELD_LAB - auto m = ProcEventMapper::getInstance(); - EvFlatFieldFromMetaData = m->newEvent(DARKFRAME, "HISTORY_MSG_FF_FROMMETADATA"); - -+ auto& options = App::get().mut_options(); -+ - hbff = Gtk::manage(new Gtk::Box()); - flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); - bindCurrentFolder (*flatFieldFile, options.lastFlatfieldDir); -@@ -332,6 +334,7 @@ void FlatField::flatFieldFileChanged() - void FlatField::flatFieldFile_Reset() - { - ffChanged = true; -+ const auto& options = App::get().options(); - - // caution: I had to make this hack, because set_current_folder() doesn't work correctly! - // Because szeva doesn't exist since he was committed to happy hunting ground in Issue 316 -diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc -index 8645771ee..54f271f83 100644 ---- a/rtgui/guiutils.cc -+++ b/rtgui/guiutils.cc -@@ -222,6 +222,7 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int - double c2x = (cparams.x + cparams.w - startx) * scale - (fullImageVisible ? 0.0 : 1.0); - double c2y = (cparams.y + cparams.h - starty) * scale - (fullImageVisible ? 0.0 : 1.0); - -+ const auto& options = App::get().options(); - // crop overlay color, linked with crop windows background - if (options.bgcolor == 0 || !useBgColor) { - cr->set_source_rgba (options.cutOverlayBrush[0], options.cutOverlayBrush[1], options.cutOverlayBrush[2], options.cutOverlayBrush[3]); -@@ -715,7 +716,7 @@ bool MyExpander::on_enter_leave_enable (GdkEventCrossing* event) - - void MyExpander::updateStyle() - { -- updateVScrollbars(options.hideTPVScrollbar); -+ updateVScrollbars(App::get().options().hideTPVScrollbar); - - //GTK318 - #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 -@@ -942,7 +943,7 @@ MyScrolledWindow::MyScrolledWindow () - - bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) - { -- if (!options.hideTPVScrollbar) { -+ if (!App::get().options().hideTPVScrollbar) { - Gtk::ScrolledWindow::on_scroll_event (event); - return true; - } -diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc -index 97c782677..6ee76948e 100644 ---- a/rtgui/histogrampanel.cc -+++ b/rtgui/histogrampanel.cc -@@ -36,14 +36,6 @@ constexpr float HistogramArea::MIN_BRIGHT; - - using ScopeType = Options::ScopeType; - -- --namespace --{ -- --const rtengine::procparams::ColorManagementParams DEFAULT_CMP; -- --} -- - // - // - // HistogramPanel -@@ -94,6 +86,7 @@ HistogramPanel::HistogramPanel () : - histogramRGBAreaVert.reset(new HistogramRGBAreaVert()); - setExpandAlignProperties(histogramRGBAreaVert.get(), false, true, Gtk::ALIGN_END, Gtk::ALIGN_FILL); - -+ const auto& options = App::get().options(); - switch (options.histogramScopeType) { - case ScopeType::NONE: - case ScopeType::HISTOGRAM_RAW: -@@ -440,7 +433,7 @@ void HistogramPanel::resized (Gtk::Allocation& req) - } - - // Store current height of the histogram -- options.histogramHeight = get_height(); -+ App::get().mut_options().histogramHeight = get_height(); - - old_height = req.get_height(); - old_width = req.get_width(); -@@ -451,7 +444,7 @@ void HistogramPanel::red_toggled () - // Update button image - showRed->set_image(showRed->get_active() ? *redImage : *redImage_g); - // Update options value -- options.histogramRed = showRed->get_active() ? true : false; -+ App::get().mut_options().histogramRed = showRed->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - } -@@ -461,7 +454,7 @@ void HistogramPanel::green_toggled () - // Update button image - showGreen->set_image(showGreen->get_active() ? *greenImage : *greenImage_g); - // Update options value -- options.histogramGreen = showGreen->get_active() ? true : false; -+ App::get().mut_options().histogramGreen = showGreen->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - } -@@ -471,7 +464,7 @@ void HistogramPanel::blue_toggled () - // Update button image - showBlue->set_image(showBlue->get_active() ? *blueImage : *blueImage_g); - // Update options value -- options.histogramBlue = showBlue->get_active() ? true : false; -+ App::get().mut_options().histogramBlue = showBlue->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - } -@@ -480,7 +473,7 @@ void HistogramPanel::value_toggled () - // Update button image - showValue->set_image(showValue->get_active() ? *valueImage : *valueImage_g); - // Update options value -- options.histogramLuma = showValue->get_active() ? true : false; -+ App::get().mut_options().histogramLuma = showValue->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - } -@@ -489,13 +482,14 @@ void HistogramPanel::chro_toggled () - // Update button image - showChro->set_image(showChro->get_active() ? *chroImage : *chroImage_g); - // Update options value -- options.histogramChroma = showChro->get_active() ? true : false; -+ App::get().mut_options().histogramChroma = showChro->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - } - - void HistogramPanel::mode_released () - { -+ auto& options = App::get().mut_options(); - // Update options value - options.histogramDrawMode = (options.histogramDrawMode + 1) % 3; - // Update button image -@@ -514,19 +508,19 @@ void HistogramPanel::brightnessWidgetValueChanged(void) - { - ConnectionBlocker blocker(brightness_changed_connection); - histogramArea->setBrightness(exp(brightnessWidget->get_value())); -- options.histogramTraceBrightness = histogramArea->getBrightness(); -+ App::get().mut_options().histogramTraceBrightness = histogramArea->getBrightness(); - } - - void HistogramPanel::brightnessUpdated(float brightness) - { - brightnessWidget->set_value(log(brightness)); -- options.histogramTraceBrightness = histogramArea->getBrightness(); -+ App::get().mut_options().histogramTraceBrightness = histogramArea->getBrightness(); - } - - void HistogramPanel::scopeOptionsToggled() - { - // Update options value -- options.histogramShowOptionButtons = scopeOptions->get_active(); -+ App::get().mut_options().histogramShowOptionButtons = scopeOptions->get_active(); - // Show/hide secondary buttons column - optionButtons->set_visible(scopeOptions->get_active()); - } -@@ -550,6 +544,7 @@ void HistogramPanel::type_selected(Gtk::RadioButton* button) - new_type = ScopeType::VECTORSCOPE_HS; - } - -+ auto& options = App::get().mut_options(); - // Do not update if selected radio button is identical - if (new_type == options.histogramScopeType) { - return; -@@ -583,6 +578,7 @@ void HistogramPanel::type_selected(Gtk::RadioButton* button) - - void HistogramPanel::type_changed() - { -+ const auto& options = App::get().options(); - switch (options.histogramScopeType) { - case ScopeType::HISTOGRAM: - showRed->show(); -@@ -651,7 +647,7 @@ void HistogramPanel::bar_toggled () - // Update button image - showBAR->set_image(showBAR->get_active() ? *barImage : *barImage_g); - // Update options value -- options.histogramBar = showBAR->get_active() ? true : false; -+ App::get().mut_options().histogramBar = showBAR->get_active() ? true : false; - // Update drawing areas - rgbv_toggled(); - // Update histogram bar visibility -@@ -721,6 +717,7 @@ void HistogramPanel::reorder (Gtk::PositionType align) - // DrawModeListener interface: - void HistogramPanel::toggleButtonMode () - { -+ const auto& options = App::get().options(); - if (options.histogramDrawMode == 0) - showMode->set_image(*mode0Image); - else if (options.histogramDrawMode == 1) -@@ -734,7 +731,7 @@ void HistogramPanel::setPanelListener(HistogramPanelListener* listener) - panel_listener = listener; - - if (listener) { -- listener->scopeTypeChanged(options.histogramScopeType); -+ listener->scopeTypeChanged(App::get().options().histogramScopeType); - } - } - -@@ -756,10 +753,10 @@ HistogramRGBArea::HistogramRGBArea () : - // Saved pointer parameters - r(-1), g(-1), b(-1), lab_L(0.f), lab_a(0.f), lab_b(0.f), pointerValid(false), - // Drawing options (initialized at options file values) -- needRed(options.histogramRed), needGreen(options.histogramGreen), -- needBlue(options.histogramBlue), needLuma(options.histogramLuma), -- needChroma(options.histogramChroma), scopeType(options.histogramScopeType), -- scaleMode(options.histogramDrawMode), showBar(options.histogramBar) -+ needRed(App::get().options().histogramRed), needGreen(App::get().options().histogramGreen), -+ needBlue(App::get().options().histogramBlue), needLuma(App::get().options().histogramLuma), -+ needChroma(App::get().options().histogramChroma), scopeType(App::get().options().histogramScopeType), -+ scaleMode(App::get().options().histogramDrawMode), showBar(App::get().options().histogramBar) - { - get_style_context()->add_class("drawingarea"); - set_name("HistogramRGBArea"); -@@ -898,7 +895,7 @@ bool HistogramRGBArea::updatePointer (const int new_r, const int new_g, const in - static_cast(g), - static_cast(b), - lab_L, lab_a, lab_b, -- cmp != nullptr ? *cmp : DEFAULT_CMP, -+ cmp != nullptr ? *cmp : App::get().fallbackColorCmp(), - true); - pointerValid = true; - } -@@ -908,6 +905,7 @@ bool HistogramRGBArea::updatePointer (const int new_r, const int new_g, const in - - void HistogramRGBArea::updateFromOptions () - { -+ const auto& options = App::get().options(); - needRed = options.histogramRed; - needGreen = options.histogramGreen; - needBlue = options.histogramBlue; -@@ -960,7 +958,7 @@ void HistogramRGBArea::factorChanged (double newFactor) - void HistogramRGBAreaHori::drawBar(const Cairo::RefPtr &cc, const double value, const double max_value, const int winw, const int winh) - { - double pos; -- if (options.histogramDrawMode < 2) { -+ if (App::get().options().histogramDrawMode < 2) { - pos = padding + value * (winw - padding * 2.0) / max_value; - } else { - pos = padding + HistogramScaling::log (max_value, value) * (winw - padding * 2.0) / max_value; -@@ -998,6 +996,7 @@ void HistogramRGBAreaHori::get_preferred_width_for_height_vfunc (int height, int - void HistogramRGBAreaVert::drawBar(const Cairo::RefPtr &cc, const double value, const double max_value, const int winw, const int winh) - { - double pos; -+ const auto& options = App::get().options(); - if (options.histogramDrawMode < 2 || options.histogramScopeType == ScopeType::PARADE || options.histogramScopeType == ScopeType::WAVEFORM) { - pos = padding + value * (winh - padding * 2.0 - 1) / max_value + 0.5; - } else { -@@ -1055,11 +1054,14 @@ HistogramArea::HistogramArea (DrawModeListener *fml) : - pointer_a(0.f), pointer_b(0.f), - pointer_valid(false), - // Drawing options -- needRed(options.histogramRed), needGreen(options.histogramGreen), needBlue(options.histogramBlue), -- needLuma(options.histogramLuma), needChroma(options.histogramChroma), -- needPointer(options.histogramBar), -- scopeType(options.histogramScopeType), -- drawMode(options.histogramDrawMode), myDrawModeListener(fml), -+ needRed(App::get().options().histogramRed), -+ needGreen(App::get().options().histogramGreen), -+ needBlue(App::get().options().histogramBlue), -+ needLuma(App::get().options().histogramLuma), -+ needChroma(App::get().options().histogramChroma), -+ needPointer(App::get().options().histogramBar), -+ scopeType(App::get().options().histogramScopeType), -+ drawMode(App::get().options().histogramDrawMode), myDrawModeListener(fml), - // Motion event management - isPressed(false), movingPosition(0.0) - { -@@ -1108,6 +1110,7 @@ void HistogramArea::get_preferred_width_for_height_vfunc (int height, int &minim - - void HistogramArea::updateFromOptions () - { -+ const auto& options = App::get().options(); - wave_buffer_dirty = wave_buffer_dirty || needRed != options.histogramRed || - needGreen != options.histogramGreen || needBlue != options.histogramBlue; - -@@ -1426,7 +1429,7 @@ bool HistogramArea::updatePointer(const int r, const int g, const int b, const r - static_cast(g), - static_cast(b), - L, pointer_a, pointer_b, -- cmp != nullptr ? *cmp : DEFAULT_CMP, -+ cmp != nullptr ? *cmp : App::get().fallbackColorCmp(), - true); - L /= 327.68f; - pointer_a /= 327.68f; -@@ -1879,6 +1882,7 @@ bool HistogramArea::on_button_press_event (GdkEventButton* event) - ) { - - drawMode = (drawMode + 1) % 3; -+ auto& options = App::get().mut_options(); - options.histogramDrawMode = (options.histogramDrawMode + 1) % 3; - - if (myDrawModeListener) { -diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc -index 2c6066442..ad24766dd 100644 ---- a/rtgui/hsvequalizer.cc -+++ b/rtgui/hsvequalizer.cc -@@ -45,7 +45,7 @@ HSVEqualizer::HSVEqualizer () : FoldableToolPanel(this, TOOL_NAME, M("TP_HSVEQUA - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - -- curveEditorG = new CurveEditorGroup (options.lastHsvCurvesDir, M("TP_HSVEQUALIZER_CHANNEL")); -+ curveEditorG = new CurveEditorGroup (App::get().mut_options().lastHsvCurvesDir, M("TP_HSVEQUALIZER_CHANNEL")); - curveEditorG->setCurveListener (this); - - hshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_HUE"))); -diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc -index b7d3a1b2d..81994abd2 100644 ---- a/rtgui/iccprofilecreator.cc -+++ b/rtgui/iccprofilecreator.cc -@@ -53,21 +53,21 @@ cmsToneCurve *make_trc(size_t size, float (*trcFunc)(float, bool)) - - ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow) - : Gtk::Dialog(M("MAIN_BUTTON_ICCPROFCREATOR"), *rtwindow, true) -- , primariesPreset(options.ICCPC_primariesPreset) -- , redPrimaryX(options.ICCPC_redPrimaryX) -- , redPrimaryY(options.ICCPC_redPrimaryY) -- , greenPrimaryX(options.ICCPC_greenPrimaryX) -- , greenPrimaryY(options.ICCPC_greenPrimaryY) -- , bluePrimaryX(options.ICCPC_bluePrimaryX) -- , bluePrimaryY(options.ICCPC_bluePrimaryY) -- , gammaPreset(options.ICCPC_gammaPreset) -- , gamma(options.ICCPC_gamma) -- , slope(options.ICCPC_slope) -- , appendParamsToDesc(options.ICCPC_appendParamsToDesc) -- , profileVersion(options.ICCPC_profileVersion) -- , illuminant(options.ICCPC_illuminant) -- , description(options.ICCPC_description) -- , copyright(options.ICCPC_copyright) -+ , primariesPreset(App::get().options().ICCPC_primariesPreset) -+ , redPrimaryX(App::get().options().ICCPC_redPrimaryX) -+ , redPrimaryY(App::get().options().ICCPC_redPrimaryY) -+ , greenPrimaryX(App::get().options().ICCPC_greenPrimaryX) -+ , greenPrimaryY(App::get().options().ICCPC_greenPrimaryY) -+ , bluePrimaryX(App::get().options().ICCPC_bluePrimaryX) -+ , bluePrimaryY(App::get().options().ICCPC_bluePrimaryY) -+ , gammaPreset(App::get().options().ICCPC_gammaPreset) -+ , gamma(App::get().options().ICCPC_gamma) -+ , slope(App::get().options().ICCPC_slope) -+ , appendParamsToDesc(App::get().options().ICCPC_appendParamsToDesc) -+ , profileVersion(App::get().options().ICCPC_profileVersion) -+ , illuminant(App::get().options().ICCPC_illuminant) -+ , description(App::get().options().ICCPC_description) -+ , copyright(App::get().options().ICCPC_copyright) - , parent(rtwindow) - { - -@@ -154,6 +154,7 @@ ICCProfileCreator::ICCProfileCreator(RTWindow *rtwindow) - aGamma = Gtk::manage(new Adjuster(M("ICCPROFCREATOR_GAMMA"), 1, 3.5, 0.00001, 2.4)); - setExpandAlignProperties(aGamma, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); - -+ const auto& options = App::get().options(); - aGamma->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - aGamma->show(); -@@ -429,6 +430,7 @@ void ICCProfileCreator::trcPresetsChanged() - - void ICCProfileCreator::storeValues() - { -+ auto& options = App::get().mut_options(); - if (iccVersion->get_active_text() == M("ICCPROFCREATOR_PROF_V4")) { - options.ICCPC_profileVersion = profileVersion = "v4"; - } else if (iccVersion->get_active_text() == M("ICCPROFCREATOR_PROF_V2")) { -@@ -683,6 +685,7 @@ void ICCProfileCreator::savePressed() - - //necessary for V2 profile - -+ auto& options = App::get().mut_options(); - if (!v2except) { - //used partially for v4, and in case of if we want to back to old manner for v2 - if (primariesPreset == "ACES-AP0" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESp0)) { -diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc -index ecd48082e..df72dc519 100644 ---- a/rtgui/icmpanel.cc -+++ b/rtgui/icmpanel.cc -@@ -84,6 +84,8 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, TOOL_NAME, M("TP_ICM_LABEL")), iu - EvICMresidtrc = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_RESIDTRC"); - EvICMwavExp = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_ICM_WAVEXP"); - -+ auto& options = App::get().mut_options(); -+ - isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = false; - - ipDialog = Gtk::manage(new MyFileChooserButton(M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); -@@ -2703,7 +2705,7 @@ void ICMPanel::saveReferencePressed() - } - - Gtk::FileChooserDialog dialog(getToplevelWindow(this), M("TP_ICM_SAVEREFERENCE"), Gtk::FILE_CHOOSER_ACTION_SAVE); -- bindCurrentFolder(dialog, options.lastProfilingReferenceDir); -+ bindCurrentFolder(dialog, App::get().mut_options().lastProfilingReferenceDir); - dialog.set_current_name(lastRefFilename); - - dialog.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); -diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc -index 209b1d0ab..94fe44c6b 100644 ---- a/rtgui/imagearea.cc -+++ b/rtgui/imagearea.cc -@@ -24,7 +24,6 @@ - #include "cropwindow.h" - #include "rtengine/refreshmap.h" - #include "rtengine/procparams.h" --#include "options.h" - #include "rtscalable.h" - - ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), fullImageWidth(0), fullImageHeight(0) -@@ -155,7 +154,7 @@ void ImageArea::setInfoText (Glib::ustring text) - - // update font - fontd.set_weight (Pango::WEIGHT_BOLD); -- const int fontSize = options.fontSize; -+ const int fontSize = App::get().options().fontSize; - // Non-absolute size is defined in "Pango units" and shall be multiplied by - // Pango::SCALE from "pt": - fontd.set_size (fontSize * Pango::SCALE); -@@ -195,7 +194,7 @@ void ImageArea::setInfoText (Glib::ustring text) - - void ImageArea::infoEnabled (bool e) - { -- -+ auto& options = App::get().mut_options(); - if (options.showInfo != e) { - options.showInfo = e; - queue_draw (); -@@ -250,7 +249,7 @@ bool ImageArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) - (*i)->expose (cr); - } - -- if (options.showInfo && !infotext.empty()) { -+ if (App::get().options().showInfo && !infotext.empty()) { - iBackBuffer.copySurface(cr); - } - -@@ -467,6 +466,7 @@ void ImageArea::addCropWindow () - cw->setCropGUIListener (cropgl); - cw->setPointerMotionListener (pmlistener); - cw->setPointerMotionHListener (pmhlistener); -+ const auto& options = App::get().options(); - int lastWidth = options.detailWindowWidth; - int lastHeight = options.detailWindowHeight; - -@@ -685,6 +685,7 @@ void ImageArea::initialImageArrived () - if (mainCropWindow) { - int w, h; - mainCropWindow->cropHandler.getFullImageSize(w, h); -+ const auto& options = App::get().options(); - if(options.prevdemo != PD_Sidecar || !options.rememberZoomAndPan || w != fullImageWidth || h != fullImageHeight) { - if (options.cropAutoFit || options.bgcolor != 0) { - mainCropWindow->zoomFitCrop(); -diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc -index 72f68887f..bab73876a 100644 ---- a/rtgui/indclippedpanel.cc -+++ b/rtgui/indclippedpanel.cc -@@ -45,6 +45,7 @@ IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : - indClippedH = Gtk::manage (new Gtk::ToggleButton ()); - indClippedH->set_relief(Gtk::RELIEF_NONE); - indClippedH->add (*Gtk::manage (new RTImage ("warning-highlights", Gtk::ICON_SIZE_LARGE_TOOLBAR))); -+ const auto& options = App::get().options(); - tt = Glib::ustring::compose("%1\n%2 = %3", M("MAIN_TOOLTIP_INDCLIPPEDH"), M("MAIN_TOOLTIP_THRESHOLD"), options.highlightThreshold); - - if (tt.find("<") == Glib::ustring::npos && tt.find(">") == Glib::ustring::npos) { -diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc -index a01a6ce77..45b80372f 100644 ---- a/rtgui/inspector.cc -+++ b/rtgui/inspector.cc -@@ -87,6 +87,7 @@ Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomSca - { - set_name("Inspector"); - -+ const auto& options = App::get().options(); - if (!options.inspectorWindow) { - window = nullptr; - } -@@ -321,6 +322,7 @@ bool Inspector::on_scroll_event(GdkEventScroll *event) - break; - } - -+ const auto& options = App::get().options(); - if ((options.zoomOnScroll && !alt) || (!options.zoomOnScroll && alt)) { - // zoom - beginZoom(event->x, event->y); -@@ -579,6 +581,7 @@ void Inspector::switchImage (const Glib::ustring &fullPath) - if (window && !window->get_visible()) - return; - -+ const auto& options = App::get().options(); - if (!options.inspectorDelay) { - doSwitchImage(); - } else { -@@ -591,6 +594,7 @@ bool Inspector::doSwitchImage() - { - Glib::ustring fullPath = next_image_path; - -+ const auto& options = App::get().options(); - // we first check the size of the list, it may have been changed in Preference - if (images.size() > size_t(options.maxInspectorBuffers)) { - // deleting the last entries -diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc -index d45b71e07..98ab7a32c 100644 ---- a/rtgui/labcurve.cc -+++ b/rtgui/labcurve.cc -@@ -107,7 +107,7 @@ LCurve::LCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_LABCURVE_LABEL"), fa - hsep3->show(); - pack_start(*hsep3, Gtk::PACK_EXPAND_WIDGET, 4); - -- curveEditorG = new CurveEditorGroup(options.lastLabCurvesDir); -+ curveEditorG = new CurveEditorGroup(App::get().mut_options().lastLabCurvesDir); - curveEditorG->setCurveListener(this); - - lshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "L*")); -diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc -index 36e558a84..6af90600f 100644 ---- a/rtgui/labgrid.cc -+++ b/rtgui/labgrid.cc -@@ -593,6 +593,7 @@ bool LabGridArea::on_motion_notify_event(GdkEventMotion *event) - } - edited = true; - grab_focus(); -+ const auto& options = App::get().options(); - if (options.adjusterMinDelay == 0) { - notifyListener(); - } else { -diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc -index 79f6313c9..a5f458523 100644 ---- a/rtgui/lensprofile.cc -+++ b/rtgui/lensprofile.cc -@@ -130,6 +130,7 @@ LensProfilePanel::LensProfilePanel() : - - const Glib::ustring defDir = LCPStore::getInstance()->getDefaultCommonDirectory(); - -+ auto& options = App::get().mut_options(); - if (!defDir.empty()) { - #ifdef _WIN32 - corrLcpFileChooser->set_show_hidden(true); // ProgramData is hidden on Windows -@@ -247,7 +248,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa - const Glib::ustring lastFolder = corrLcpFileChooser->get_current_folder(); - corrLcpFileChooser->set_current_folder(lastFolder); - corrLcpFileChooser->unselect_all(); -- bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir); -+ bindCurrentFolder(*corrLcpFileChooser, App::get().mut_options().lastLensProfileDir); - updateLCPDisabled(false); - } - else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { -diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc -index d533727a0..9cb042680 100644 ---- a/rtgui/locallab.cc -+++ b/rtgui/locallab.cc -@@ -27,8 +27,6 @@ - using namespace rtengine; - using namespace procparams; - --extern Options options; -- - const Glib::ustring Locallab::TOOL_NAME = "locallab"; - - /* ==== LocallabToolList ==== */ -@@ -231,7 +229,7 @@ Locallab::Locallab(): - - // Update Locallab tools advice tooltips visibility based on saved option - for (auto tool : locallabTools) { -- tool->updateAdviceTooltips(options.showtooltip); -+ tool->updateAdviceTooltips(App::get().options().showtooltip); - } - - // By default, if no photo is loaded, all Locallab tools are removed and it's not possible to add them -diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc -index 31bf1e1a5..35e29d7c1 100644 ---- a/rtgui/locallabtools.cc -+++ b/rtgui/locallabtools.cc -@@ -74,7 +74,6 @@ void update_ghs_curve( - using namespace rtengine; - using namespace procparams; - --extern Options options; - static double blurSlider2radius(double sval) - { - // Slider range: 0 - 1000 -@@ -241,7 +240,7 @@ void LocallabTool::addLocallabTool(bool raiseEvent) - if (needMode) { - // Set complexity mode according to chosen default one - complexityConn.block(true); -- complexity->set_active(options.complexity); -+ complexity->set_active(App::get().options().complexity); - complexityConn.block(false); - - // Update GUI accordingly -@@ -515,19 +514,19 @@ LocallabColor::LocallabColor(): - expcurvcol(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPCURV")))), - labqualcurv(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_QUALCURV_METHOD") + ":"))), - qualitycurveMethod(Gtk::manage(new MyComboBoxText())), -- llCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_LUM"))), -+ llCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_LUM"))), - llshape(static_cast(llCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - ccshape(static_cast(llCurveEditorG->addCurve(CT_Diagonal, "C(C)"))), -- clCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CH"))), -+ clCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_CH"))), - clshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "C(L)"))), - lcshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "L(C)"))), -- HCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), -+ HCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), - LHshape(static_cast(HCurveEditorG->addCurve(CT_Flat, "L(h)", nullptr, false, true))), -- H3CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), -+ H3CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), - CHshape(static_cast(H3CurveEditorG->addCurve(CT_Flat, "C(h)", nullptr, false, true))), -- H2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), -+ H2CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), - HHshape(static_cast(H2CurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))), -- rgbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_RGB"))), -+ rgbCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_RGB"))), - toneMethod(Gtk::manage(new MyComboBoxText())), - rgbshape(static_cast(rgbCurveEditorG->addCurve(CT_Diagonal, "", toneMethod))), - special(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_SPECIAL")))), -@@ -546,8 +545,8 @@ LocallabColor::LocallabColor(): - showmaskcolMethod(Gtk::manage(new MyComboBoxText())), - showmaskcolMethodinv(Gtk::manage(new MyComboBoxText())), - enaColorMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -- maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir,"", 1)), -+// maskCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -+ maskCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir,"", 1)), - CCmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -567,12 +566,12 @@ LocallabColor::LocallabColor(): - gammaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), - slomaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), - shadmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), -- // maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))), -- maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "")), -+ // maskHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))), -+ maskHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "")), - HHhmaskshape(static_cast(maskHCurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))), -- mask2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskshape(static_cast(mask2CurveEditorG->addCurve(CT_Diagonal, "L(L)"))), -- mask2CurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), -+ mask2CurveEditorGwav(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), - LLmaskcolshapewav(static_cast(mask2CurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), - csThresholdcol(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) - { -@@ -2744,7 +2743,7 @@ LocallabExposure::LocallabExposure(): - shadex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEX"), 0, 100, 1, 0))), - shcompr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEXCOMP"), 0, 100, 1, 50))), - expchroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EXPCHROMA"), -50, 100, 1, 5))), -- curveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CURVEEDITOR_TONES_LABEL"))), -+ curveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_CURVEEDITOR_TONES_LABEL"))), - shapeexpos(static_cast(curveEditorG->addCurve(CT_Diagonal, ""))), - exprecove(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))), - maskusablee(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))), -@@ -2764,8 +2763,8 @@ LocallabExposure::LocallabExposure(): - showmaskexpMethodinv(Gtk::manage(new MyComboBoxText())), - enaExpMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), - enaExpMaskaft(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASKAFT")))), -- // maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+ // maskexpCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ maskexpCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -2778,7 +2777,7 @@ LocallabExposure::LocallabExposure(): - gradFramemask(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADFRA")))), - strmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2., 2., 0.05, 0.))), - angmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180., 180., 0.1, 0.))), -- mask2expCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2expCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskexpshape(static_cast(mask2expCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - Evlocallabtmosatur(ProcEventMapper::getInstance()->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_TMO_SATUR")) - -@@ -4345,8 +4344,8 @@ LocallabShadow::LocallabShadow(): - showmaskSHMethod(Gtk::manage(new MyComboBoxText())), - showmaskSHMethodinv(Gtk::manage(new MyComboBoxText())), - enaSHMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// maskSHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- maskSHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// maskSHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ maskSHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -4356,7 +4355,7 @@ LocallabShadow::LocallabShadow(): - chromaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), - gammaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), - slomaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), -- mask2SHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2SHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - LmaskSHshape(static_cast(mask2SHCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - fatSHFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_FATSHFRA")))), - fatamountSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATAMOUNT"), 1., 100., 1., 1.))), -@@ -6157,7 +6156,7 @@ LocallabVibrance::LocallabVibrance(): - pastSatTog(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PASTSATTOG")))), - sensiv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 30))),//reused - unused here, but used for normalize_mean_dt - previewvib(Gtk::manage(new Gtk::ToggleButton(M("TP_LOCALLAB_PREVIEW")))), -- curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))), -+ curveEditorGG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))), - skinTonesCurve(static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES")))), - exprecovv(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))), - maskusablev(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))), -@@ -6175,8 +6174,8 @@ LocallabVibrance::LocallabVibrance(): - expmaskvib(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWVI")))), - showmaskvibMethod(Gtk::manage(new MyComboBoxText())), - enavibMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), -- // maskvibCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- maskvibCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+ // maskvibCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ maskvibCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -6186,7 +6185,7 @@ LocallabVibrance::LocallabVibrance(): - chromaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), - gammaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), - slomaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), -- mask2vibCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2vibCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskvibshape(static_cast(mask2vibCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) - { - auto m = ProcEventMapper::getInstance(); -@@ -7694,7 +7693,7 @@ LocallabBlur::LocallabBlur(): - expdenoisenl(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_NLFRA")))), - expdenoiselum(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOIWAVLUM")))), - expdenoisech(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOIWAVCH")))), -- LocalcurveEditorwavden(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVDEN"))), -+ LocalcurveEditorwavden(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVDEN"))), - wavshapeden(static_cast(LocalcurveEditorwavden->addCurve(CT_Flat, "", nullptr, false, false))), - // lCLabels(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_LCLABELS")))), - lCLabels(Gtk::manage(new Gtk::Label("-----------------"))), -@@ -7720,7 +7719,7 @@ LocallabBlur::LocallabBlur(): - noiselumdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMDETAIL"), 0., 100., 0.01, 50.))), - noiselequal(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELEQUAL"), -2, 10, 1, 7, Gtk::manage(new RTImage("circle-white-small")), Gtk::manage(new RTImage("circle-black-small"))))), - noisegam(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISEGAM"), 1.0, 5., 0.1, 1.))), -- LocalcurveEditorwavhue(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_WAVELET_DENOISEHUE"))), -+ LocalcurveEditorwavhue(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_WAVELET_DENOISEHUE"))), - wavhue(static_cast(LocalcurveEditorwavhue->addCurve(CT_Flat, "", nullptr, false, true))), - noisechrof(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROFINE"), MINCHRO, MAXCHRO, 0.01, 0.))), - noisechroc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))), -@@ -7752,8 +7751,8 @@ LocallabBlur::LocallabBlur(): - showmaskblMethod(Gtk::manage(new MyComboBoxText())), - showmaskblMethodtyp(Gtk::manage(new MyComboBoxText())), - enablMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// maskblCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- maskblCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// maskblCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ maskblCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -7769,9 +7768,9 @@ LocallabBlur::LocallabBlur(): - slomaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), - shadmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_HIGHMASKCOL"), 0, 100, 1, 0))), - shadmaskblsha(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), -- mask2blCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ mask2blCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), - Lmaskblshape(static_cast(mask2blCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), -- mask2blCurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), -+ mask2blCurveEditorGwav(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), - LLmaskblshapewav(static_cast(mask2blCurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), - quaHBox(Gtk::manage(new Gtk::Box())), - csThresholdblur(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) -diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc -index aabdd199a..9f982031e 100644 ---- a/rtgui/locallabtools2.cc -+++ b/rtgui/locallabtools2.cc -@@ -35,8 +35,6 @@ - using namespace rtengine; - using namespace procparams; - --extern Options options; -- - static double retiSlider2neigh(double sval) - { - // Slider range: 0 - 5000 -@@ -144,8 +142,8 @@ LocallabTone::LocallabTone(): - showmasktmMethod(Gtk::manage(new MyComboBoxText())), - enatmMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), - enatmMaskaft(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_AFTER_MASK")))), --// masktmCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- masktmCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// masktmCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ masktmCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -155,7 +153,7 @@ LocallabTone::LocallabTone(): - chromasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), - gammasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.05, 5.0, 0.01, 1.))), - slomasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), -- mask2tmCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2tmCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmasktmshape(static_cast(mask2tmCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) - { - auto m = ProcEventMapper::getInstance(); -@@ -899,12 +897,12 @@ LocallabRetinex::LocallabRetinex(): - lightnessreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTRETI"), 0.01, 4.0, 0.01, 1.))), - cliptm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLIPTM"), 0.02, 2.0, 0.01, 1.))), - softradiusret(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRETI"), 0.0, 100.0, 0.5, 40.))), -- LocalcurveEditortransT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONMAP"))), -+ LocalcurveEditortransT(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONMAP"))), - cTtransshape(static_cast(LocalcurveEditortransT->addCurve(CT_Flat, "", nullptr, false, false))), - mMLabels(Gtk::manage(new Gtk::Label("---"))), - transLabels(Gtk::manage(new Gtk::Label("---"))), - transLabels2(Gtk::manage(new Gtk::Label("---"))), -- LocalcurveEditorgainT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONGAIN"))), -+ LocalcurveEditorgainT(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONGAIN"))), - cTgainshape(static_cast(LocalcurveEditorgainT->addCurve(CT_Flat, "", nullptr, false, false))), - exprecovr(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))), - maskusabler(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))), -@@ -917,8 +915,8 @@ LocallabRetinex::LocallabRetinex(): - showmaskretiMethod(Gtk::manage(new MyComboBoxText())), - enaretiMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), - enaretiMasktmap(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TM_MASK")))), --// maskretiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- maskretiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// maskretiCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ maskretiCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -928,7 +926,7 @@ LocallabRetinex::LocallabRetinex(): - chromaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), - gammaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.05, 5.0, 0.01, 1.))), - slomaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), -- mask2retiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2retiCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskretishape(static_cast(mask2retiCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - inversret(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) - { -@@ -2536,7 +2534,7 @@ LocallabContrast::LocallabContrast(): - contFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CONTWFRA")))), - sigmalc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), - offslc(Gtk::manage(new Adjuster(M("TP_WAVELET_WAVOFFSET"), 0.33, 1.6, 0.01, 1.))), -- LocalcurveEditorwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), -+ LocalcurveEditorwav(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), - wavshape(static_cast(LocalcurveEditorwav->addCurve(CT_Flat, "", nullptr, false, false))), - csThreshold(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLD"), 0, 9, 0, 0, 7, 5, 0, false))), - processwav(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_PROCESSWAV")))), -@@ -2569,7 +2567,7 @@ LocallabContrast::LocallabContrast(): - wavedg(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EDGFRA")))), - strengthw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDVAL"), 0., 100.0, 0.5, 0.))), - sigmaed(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), -- LocalcurveEditorwavedg(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVEDG"))), -+ LocalcurveEditorwavedg(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVEDG"))), - wavshapeedg(static_cast(LocalcurveEditorwavedg->addCurve(CT_Flat, "", nullptr, false, false))), - gradw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECT"), 0., 100.0, 0.5, 90.))), - waveshow(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EDGSHOW")))), -@@ -2586,7 +2584,7 @@ LocallabContrast::LocallabContrast(): - levelblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELBLUR"), 0., 100., 0.5, 0.))), - sigmabl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), - chromablu(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMABLU"), 0.0, 5., 0.1, 0.))), -- LocalcurveEditorwavlev(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVLEV"))), -+ LocalcurveEditorwavlev(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVLEV"))), - wavshapelev(static_cast(LocalcurveEditorwavlev->addCurve(CT_Flat, "", nullptr, false, false))), - residblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDBLUR"), 0., 100., 0.5, 0.))), - blurlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_BLURLC")))), -@@ -2595,10 +2593,10 @@ LocallabContrast::LocallabContrast(): - sigma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), - offset(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OFFSETWAV"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small")), Gtk::manage(new RTImage("circle-white-small"))))), - chromalev(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMALEV"), 0.1, 5., 0.1, 1.))), -- LocalcurveEditorwavcon(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCON"))), -+ LocalcurveEditorwavcon(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVCON"))), - wavshapecon(static_cast(LocalcurveEditorwavcon->addCurve(CT_Flat, "", nullptr, false, false))), - wavcompre(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_COMPREFRA")))), -- LocalcurveEditorwavcompre(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMPRE"))), -+ LocalcurveEditorwavcompre(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMPRE"))), - wavshapecompre(static_cast(LocalcurveEditorwavcompre->addCurve(CT_Flat, "", nullptr, false, false))), - sigmadr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), - threswav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESWAV"), 0.9, 2., 0.01, 1.4))), -@@ -2606,7 +2604,7 @@ LocallabContrast::LocallabContrast(): - wavcomp(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_COMPFRA")))), - sigmadc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 3., 0.01, 1.))), - deltad(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DELTAD"), -3., 3., 0.1, 0.))),//, Gtk::manage(new RTImage("circle-black-small")), Gtk::manage(new RTImage("circle-white-small"))))), -- LocalcurveEditorwavcomp(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMP"))), -+ LocalcurveEditorwavcomp(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMP"))), - wavshapecomp(static_cast(LocalcurveEditorwavcomp->addCurve(CT_Flat, "", nullptr, false, false))), - //fatres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATRES"), 0., 100., 1., 0.))), - fftwlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))), -@@ -2621,15 +2619,15 @@ LocallabContrast::LocallabContrast(): - expmasklc(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWLC")))), - showmasklcMethod(Gtk::manage(new MyComboBoxText())), - enalcMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// masklcCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -- masklcCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// masklcCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+ masklcCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), - blendmasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), - radmasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 0.))), - chromasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), -- mask2lcCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2lcCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmasklcshape(static_cast(mask2lcCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) - { - auto m = ProcEventMapper::getInstance(); -@@ -4767,8 +4765,8 @@ decaycb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKDDECAY"), 0.5, 4., 0.1, 2.)) - expmaskcb(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWCB")))), - showmaskcbMethod(Gtk::manage(new MyComboBoxText())), - enacbMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// maskcbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), --maskcbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// maskcbCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), -+maskcbCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -4778,7 +4776,7 @@ lapmaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, - chromaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), - gammaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), - slomaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), --mask2cbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+mask2cbCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskcbshape(static_cast(mask2cbCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - - lumacontrastMinusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS")))), -@@ -5597,7 +5595,7 @@ LocallabLog::LocallabLog(): - saturl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SATURV"), -100., 100., 0.5, 0.))), - chroml(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROML"), -100., 100., 0.5, 0.))), - expL(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_LOGEXP")))), -- //CurveEditorL(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_LOGCONTQ"))), -+ //CurveEditorL(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_LOGCONTQ"))), - //LshapeL(static_cast(CurveEditorL->addCurve(CT_Diagonal, "Q(Q)"))), - targabs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOURCE_ABS"), 0.01, 16384.0, 0.01, 16.0))), - surround(Gtk::manage(new MyComboBoxText())), -@@ -5620,15 +5618,15 @@ LocallabLog::LocallabLog(): - expmaskL(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWC")))), - showmaskLMethod(Gtk::manage(new MyComboBoxText())), - enaLMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// maskCurveEditorL(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -- maskCurveEditorL(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// maskCurveEditorL(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -+ maskCurveEditorL(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskshapeL(static_cast(maskCurveEditorL->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskshapeL(static_cast(maskCurveEditorL->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskshapeL(static_cast(maskCurveEditorL->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), - blendmaskL(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), - radmaskL(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 0.))), - chromaskL(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), -- mask2CurveEditorL(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2CurveEditorL(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - LmaskshapeL(static_cast(mask2CurveEditorL->addCurve(CT_Diagonal, "L(L)"))) - - -@@ -7101,8 +7099,8 @@ LocallabMask::LocallabMask(): - softradiusmask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.5, 1.))), - showmask_Method(Gtk::manage(new MyComboBoxText())), - enamask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), --// mask_CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -- mask_CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+// mask_CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), -+ mask_CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmask_shape(static_cast(mask_CurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmask_shape(static_cast(mask_CurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmask_shape(static_cast(mask_CurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -7120,11 +7118,11 @@ LocallabMask::LocallabMask(): - gammask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), - slopmask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), - shadmask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), -- mask_HCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))), -+ mask_HCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))), - HHhmask_shape(static_cast(mask_HCurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))), -- mask2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmask_shape(static_cast(mask2CurveEditorG->addCurve(CT_Diagonal, "L(L)"))), -- mask2CurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), -+ mask2CurveEditorGwav(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), - LLmask_shapewav(static_cast(mask2CurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), - csThresholdmask(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))), - gradFramemask(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADFRA")))), -@@ -8076,7 +8074,7 @@ Locallabcie::Locallabcie(): - expwavjz(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_JZWAVEXP")))), - contFramejz(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CONTWFRA")))), - sigmalcjz(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), -- LocalcurveEditorwavjz(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), -+ LocalcurveEditorwavjz(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), - wavshapejz(static_cast(LocalcurveEditorwavjz->addCurve(CT_Flat, "", nullptr, false, false))), - csThresholdjz(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLD"), 0, 9, 0, 0, 7, 4, 0, false))), - clariFramejz(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CLARIFRA")))), -@@ -8209,24 +8207,24 @@ Locallabcie::Locallabcie(): - rstprotectcie(Gtk::manage(new Adjuster(M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.))), - chromlcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROML"), -100., 100., 0.5, 0.))), - huecie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_HUECIE"), -100., 100., 0.1, 0.))), -- cieCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CURVES_CIE"))), -+ cieCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_CURVES_CIE"))), - toneMethodcie(Gtk::manage(new MyComboBoxText())), - shapecie(static_cast(cieCurveEditorG->addCurve(CT_Diagonal, "", toneMethodcie))), -- cieCurveEditorG2(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_COLOR_CIE"))), -+ cieCurveEditorG2(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_COLOR_CIE"))), - toneMethodcie2(Gtk::manage(new MyComboBoxText())), - shapecie2(static_cast(cieCurveEditorG2->addCurve(CT_Diagonal, "", toneMethodcie2))), - - chromjzcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_JZCHROM"), -100., 100., 0.5, 0.))), - saturjzcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_JZSAT"), -100., 100., 0.5, 0.))), - huejzcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_JZHUECIE"), -100., 100., 0.1, 0.))), -- jz1CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+ jz1CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - shapejz(static_cast(jz1CurveEditorG->addCurve(CT_Diagonal, "Jz(J)"))), - shapecz(static_cast(jz1CurveEditorG->addCurve(CT_Diagonal, "Cz(C)"))), - - HFramejz(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_JZHFRA")))), - JzHFramejz(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_JZHJZFRA")))), -- jz2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -- jz3CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+ jz2CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), -+ jz3CurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - shapeczjz(static_cast(jz1CurveEditorG->addCurve(CT_Diagonal, "Cz(J)"))), - HHshapejz(static_cast(jz3CurveEditorG->addCurve(CT_Flat, "Hz(Hz)", nullptr, false, true))), - CHshapejz(static_cast(jz3CurveEditorG->addCurve(CT_Flat, "Cz(Hz)", nullptr, false, true))), -@@ -8261,7 +8259,7 @@ Locallabcie::Locallabcie(): - showmaskcieMethod(Gtk::manage(new MyComboBoxText())), - enacieMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), - enacieMaskall(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASKALL")))), -- maskcieCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "", 1)), -+ maskcieCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "", 1)), - CCmaskcieshape(static_cast(maskcieCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))), - LLmaskcieshape(static_cast(maskcieCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))), - HHmaskcieshape(static_cast(maskcieCurveEditorG->addCurve(CT_Flat, "LC(h)", nullptr, false, true))), -@@ -8280,12 +8278,12 @@ Locallabcie::Locallabcie(): - slomaskcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), - highmaskcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_HIGHMASKCOL"), 0, 100, 1, 0))), - shadmaskcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), -- maskcieHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, "")), -+ maskcieHCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, "")), - HHhmaskcieshape(static_cast(maskcieHCurveEditorG->addCurve(CT_Flat, "h(h)", nullptr, false, true))), -- mask2cieCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), -+ mask2cieCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), - Lmaskcieshape(static_cast(mask2cieCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), - wavFramecie(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK_2")))), -- mask2cieCurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), -+ mask2cieCurveEditorGwav(new CurveEditorGroup(App::get().mut_options().lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), - LLmaskcieshapewav(static_cast(mask2cieCurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), - quaHcieBox(Gtk::manage(new Gtk::Box())), - csThresholdcie(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) -diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc -index 8c8d73418..206b51e19 100644 ---- a/rtgui/lockablecolorpicker.cc -+++ b/rtgui/lockablecolorpicker.cc -@@ -27,13 +27,6 @@ - #include "multilangmgr.h" - #include "navigator.h" - --namespace --{ -- --const rtengine::procparams::ColorManagementParams DEFAULT_CMP; -- --} -- - LockableColorPicker::LockableColorPicker (CropWindow* cropWindow, rtengine::procparams::ColorManagementParams *color_management_params) - : cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(0, 0), size(Size::S15), - color_management_params(color_management_params), validity(Validity::OUTSIDE), -@@ -54,6 +47,7 @@ void LockableColorPicker::updateBackBuffer () - - Glib::RefPtr pangoContext = iArea->get_pango_context (); - Pango::FontDescription fontd = iArea->get_style_context()->get_font(); -+ const auto& options = App::get().options(); - // set font family and size - fontd.set_family(options.CPFontFamily == "default" ? "sans" : options.CPFontFamily); - const int fontSize = options.CPFontFamily == "default" ? 8 : options.CPFontSize; // pt -@@ -293,7 +287,8 @@ void LockableColorPicker::setRGB (const float R, const float G, const float B, c - static_cast(255 * g), - static_cast(255 * b), - L, a, bb, -- color_management_params != nullptr ? *color_management_params : DEFAULT_CMP, -+ color_management_params != nullptr -+ ? *color_management_params : App::get().fallbackColorCmp(), - true); - L /= 327.68f; - a /= 327.68f; -diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc -index c754416a9..a03daaac7 100644 ---- a/rtgui/main-cli.cc -+++ b/rtgui/main-cli.cc -@@ -56,14 +56,6 @@ - // Set this to 1 to make RT work when started with Eclipse and arguments, at least on Windows platform - #define ECLIPSE_ARGS 0 - --// stores path to data files --Glib::ustring argv0; --Glib::ustring creditsPath; --Glib::ustring licensePath; --Glib::ustring argv1; --//bool simpleEditor; --//Glib::Threads::Thread* mainThread; -- - namespace - { - -@@ -90,7 +82,7 @@ int main (int argc, char **argv) - - Gio::init (); - -- //mainThread = Glib::Threads::Thread::self(); -+ auto& app = App::get(); - - #ifdef BUILD_BUNDLE - char exname[512] = {0}; -@@ -106,38 +98,36 @@ int main (int argc, char **argv) - strncpy (exname, argv[0], 511); - } - --#endif -+#endif // _WIN32 - exePath = Glib::path_get_dirname (exname); - - // set paths - if (Glib::path_is_absolute (DATA_SEARCH_PATH)) { -- argv0 = DATA_SEARCH_PATH; -+ app.setArgv0(DATA_SEARCH_PATH); - } else { -- argv0 = Glib::build_filename (exePath, DATA_SEARCH_PATH); -+ app.setArgv0(Glib::build_filename(exePath, DATA_SEARCH_PATH)); - } - - if (Glib::path_is_absolute (CREDITS_SEARCH_PATH)) { -- creditsPath = CREDITS_SEARCH_PATH; -+ app.setCreditsPath(CREDITS_SEARCH_PATH); - } else { -- creditsPath = Glib::build_filename (exePath, CREDITS_SEARCH_PATH); -+ app.setCreditsPath(Glib::build_filename(exePath, CREDITS_SEARCH_PATH)); - } - - if (Glib::path_is_absolute (LICENCE_SEARCH_PATH)) { -- licensePath = LICENCE_SEARCH_PATH; -+ app.setLicensePath(LICENCE_SEARCH_PATH); - } else { -- licensePath = Glib::build_filename (exePath, LICENCE_SEARCH_PATH); -+ app.setLicensePath(Glib::build_filename(exePath, LICENCE_SEARCH_PATH)); - } -- -- options.rtSettings.lensfunDbDirectory = LENSFUN_DB_PATH; -- options.rtSettings.lensfunDbBundleDirectory = LENSFUN_DB_PATH; -- - #else -- argv0 = DATA_SEARCH_PATH; -- creditsPath = CREDITS_SEARCH_PATH; -- licensePath = LICENCE_SEARCH_PATH; -+ app.setArgv0(DATA_SEARCH_PATH); -+ app.setCreditsPath(CREDITS_SEARCH_PATH); -+ app.setLicensePath(LICENCE_SEARCH_PATH); -+#endif // BUILD_BUNDLE -+ -+ Options& options = app.mut_options(); - options.rtSettings.lensfunDbDirectory = LENSFUN_DB_PATH; - options.rtSettings.lensfunDbBundleDirectory = LENSFUN_DB_PATH; --#endif - - bool quickstart = dontLoadCache (argc, argv); - -@@ -256,6 +246,7 @@ int processLineParams ( int argc, char **argv ) - std::string outputType; - unsigned errors = 0; - -+ auto& options = App::get().mut_options(); - for ( int iArg = 1; iArg < argc; iArg++) { - Glib::ustring currParam (argv[iArg]); - if ( currParam.empty() ) { -@@ -482,7 +473,7 @@ int processLineParams ( int argc, char **argv ) - - if (sideProcParams && skipIfNoSidecar) { - // look for the sidecar proc params -- if (!Glib::file_test (fileName + paramFileExtension, Glib::FILE_TEST_EXISTS)) { -+ if (!Glib::file_test (fileName + App::PARAM_FILE_EXTENSION, Glib::FILE_TEST_EXISTS)) { - std::cout << "\"" << fileName << "\" has no side-car file. Image skipped." << std::endl; - continue; - } -@@ -504,7 +495,7 @@ int processLineParams ( int argc, char **argv ) - case 'h': - case '?': - default: { -- Glib::ustring pparamsExt = paramFileExtension.substr (1); -+ Glib::ustring pparamsExt = App::PARAM_FILE_EXTENSION.substr (1); - std::cout << " An advanced, cross-platform program for developing raw photos." << std::endl; - std::cout << std::endl; - std::cout << " Website: http://www.rawtherapee.com/" << std::endl; -@@ -579,9 +570,9 @@ int processLineParams ( int argc, char **argv ) - } - } - } else { -- argv1 = Glib::ustring (fname_to_utf8 (argv[iArg])); -+ App::get().setArgv1(Glib::ustring (fname_to_utf8 (argv[iArg]))); - #if ECLIPSE_ARGS -- argv1 = argv1.substr (1, argv1.length() - 2); -+ App::get().setArgv1(App::get().argv1().substr (1, App::get().argv1().length() - 2)); - #endif - - if ( outputDirectory ) { -@@ -623,7 +614,7 @@ int processLineParams ( int argc, char **argv ) - } - } - -- if ( !argv1.empty() ) { -+ if ( !App::get().argv1().empty() ) { - return 1; - } - -@@ -635,7 +626,7 @@ int processLineParams ( int argc, char **argv ) - rawParams = new rtengine::procparams::PartialProfile (true, true); - Glib::ustring profPath = options.findProfilePath (options.defProfRaw); - -- if (options.is_defProfRawMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && rawParams->load (profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename (profPath, Glib::path_get_basename (options.defProfRaw) + paramFileExtension)))) { -+ if (options.is_defProfRawMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && rawParams->load (profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename (profPath, Glib::path_get_basename (options.defProfRaw) + App::PARAM_FILE_EXTENSION)))) { - std::cerr << "Error: default raw processing profile not found." << std::endl; - rawParams->deleteInstance(); - delete rawParams; -@@ -646,7 +637,7 @@ int processLineParams ( int argc, char **argv ) - imgParams = new rtengine::procparams::PartialProfile (true); - profPath = options.findProfilePath (options.defProfImg); - -- if (options.is_defProfImgMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && imgParams->load (profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename (profPath, Glib::path_get_basename (options.defProfImg) + paramFileExtension)))) { -+ if (options.is_defProfImgMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && imgParams->load (profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename (profPath, Glib::path_get_basename (options.defProfImg) + App::PARAM_FILE_EXTENSION)))) { - std::cerr << "Error: default non-raw processing profile not found." << std::endl; - imgParams->deleteInstance(); - delete imgParams; -@@ -750,7 +741,7 @@ int processLineParams ( int argc, char **argv ) - do { - if (sideProcParams && i == sideCarFilePos) { - // using the sidecar file -- Glib::ustring sideProcessingParams = inputFile + paramFileExtension; -+ Glib::ustring sideProcessingParams = inputFile + App::PARAM_FILE_EXTENSION; - - // the "load" method don't reset the procparams values anymore, so values found in the procparam file override the one of currentParams - if ( !Glib::file_test ( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { -@@ -811,7 +802,7 @@ int processLineParams ( int argc, char **argv ) - std::cerr << "Error saving to: " << outputFile << std::endl; - } else { - if ( copyParamsFile ) { -- Glib::ustring outputProcessingParams = outputFile + paramFileExtension; -+ Glib::ustring outputProcessingParams = outputFile + App::PARAM_FILE_EXTENSION; - currentParams.save ( outputProcessingParams ); - } - } -diff --git a/rtgui/main.cc b/rtgui/main.cc -index e11042e49..ded7076be 100644 ---- a/rtgui/main.cc -+++ b/rtgui/main.cc -@@ -61,15 +61,7 @@ - #define ECLIPSE_ARGS 0 - - // stores path to data files --Glib::ustring argv0; --Glib::ustring creditsPath; --Glib::ustring licensePath; --Glib::ustring argv1; - Glib::ustring argv2; --bool simpleEditor = false; --bool gimpPlugin = false; --bool remote = false; --//Glib::Threads::Thread* mainThread; - - namespace { - -@@ -104,6 +96,8 @@ static void myGdkLockLeave() - //int processLineParams ( int argc, char **argv ); - int processLineParams ( int argc, char **argv ) - { -+ auto& app = App::get(); -+ - int ret = 1; - for ( int iArg = 1; iArg < argc; iArg++) { - Glib::ustring currParam (argv[iArg]); -@@ -134,8 +128,8 @@ int processLineParams ( int argc, char **argv ) - #ifndef __APPLE__ // TODO agriggio - there seems to be already some "single instance app" support for OSX in rtwindow. Disabling it here until I understand how to merge the two - - case 'R': -- if (!gimpPlugin) { -- remote = true; -+ if (!app.isGimpPlugin()) { -+ app.setIsRemote(true); - } - - break; -@@ -143,9 +137,9 @@ int processLineParams ( int argc, char **argv ) - - case 'g': - if (currParam == "-gimp") { -- gimpPlugin = true; -- simpleEditor = true; -- remote = false; -+ app.setIsGimpPlugin(true); -+ app.setIsSimpleEditor(true); -+ app.setIsRemote(true); - break; - } - -@@ -180,17 +174,17 @@ int processLineParams ( int argc, char **argv ) - } - } - } else { -- if (argv1.empty()) { -- argv1 = Glib::ustring (fname_to_utf8 (argv[iArg])); -+ if (app.argv1().empty()) { -+ app.setArgv1(Glib::ustring (fname_to_utf8 (argv[iArg]))); - #if ECLIPSE_ARGS -- argv1 = argv1.substr (1, argv1.length() - 2); -+ app.setArgv1(app.argv1().substr (1, app.argv1().length() - 2)); - #endif -- } else if (gimpPlugin) { -+ } else if (app.isGimpPlugin()) { - argv2 = Glib::ustring (fname_to_utf8 (argv[iArg])); - break; - } - -- if (!gimpPlugin) { -+ if (!app.isGimpPlugin()) { - break; - } - } -@@ -211,6 +205,7 @@ bool init_rt() - - #ifndef _WIN32 - -+ const auto& options = App::get().options(); - // Move the old path to the new one if the new does not exist - if (Glib::file_test (Glib::build_filename (options.rtdir, "cache"), Glib::FILE_TEST_IS_DIR) && !Glib::file_test (options.cacheBaseDir, Glib::FILE_TEST_IS_DIR)) { - g_rename (Glib::build_filename (options.rtdir, "cache").c_str (), options.cacheBaseDir.c_str ()); -@@ -230,7 +225,7 @@ void cleanup_rt() - - RTWindow *create_rt_window() - { -- Glib::ustring icon_path = Glib::build_filename (argv0, "icons"); -+ Glib::ustring icon_path = Glib::build_filename (App::get().argv0(), "icons"); - Glib::RefPtr defaultIconTheme = Gtk::IconTheme::get_default(); - defaultIconTheme->append_search_path (icon_path); - -@@ -332,6 +327,7 @@ private: - - void show_gimp_plugin_info_dialog(Gtk::Window *parent) - { -+ auto& options = App::get().mut_options(); - if (options.gimpPluginShowInfoDialog) { - Gtk::MessageDialog info(*parent, M("GIMP_PLUGIN_INFO"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true); - Gtk::Box *box = info.get_message_area(); -@@ -351,13 +347,6 @@ int main (int argc, char **argv) - setlocale (LC_ALL, ""); - setlocale (LC_NUMERIC, "C"); // to set decimal point to "." - -- simpleEditor = false; -- gimpPlugin = false; -- remote = false; -- argv0 = ""; -- argv1 = ""; -- argv2 = ""; -- - Glib::init(); // called by Gtk::Main, but this may be important for thread handling, so we call it ourselves now - Gio::init (); - -@@ -368,6 +357,8 @@ int main (int argc, char **argv) - } - #endif - -+ auto& app = App::get(); -+ - #ifdef BUILD_BUNDLE - char exname[512] = {0}; - Glib::ustring exePath; -@@ -382,38 +373,35 @@ int main (int argc, char **argv) - strncpy (exname, argv[0], 511); - } - --#endif -+#endif // _WIN32 - exePath = Glib::path_get_dirname (exname); - - // set paths - if (Glib::path_is_absolute (DATA_SEARCH_PATH)) { -- argv0 = DATA_SEARCH_PATH; -+ app.setArgv0(DATA_SEARCH_PATH); - } else { -- argv0 = Glib::build_filename (exePath, DATA_SEARCH_PATH); -+ app.setArgv0(Glib::build_filename(exePath, DATA_SEARCH_PATH)); - } - - if (Glib::path_is_absolute (CREDITS_SEARCH_PATH)) { -- creditsPath = CREDITS_SEARCH_PATH; -+ app.setCreditsPath(CREDITS_SEARCH_PATH); - } else { -- creditsPath = Glib::build_filename (exePath, CREDITS_SEARCH_PATH); -+ app.setCreditsPath(Glib::build_filename(exePath, CREDITS_SEARCH_PATH)); - } - - if (Glib::path_is_absolute (LICENCE_SEARCH_PATH)) { -- licensePath = LICENCE_SEARCH_PATH; -+ app.setLicensePath(LICENCE_SEARCH_PATH); - } else { -- licensePath = Glib::build_filename (exePath, LICENCE_SEARCH_PATH); -+ app.setLicensePath(Glib::build_filename(exePath, LICENCE_SEARCH_PATH)); - } -- -- options.rtSettings.lensfunDbDirectory = LENSFUN_DB_PATH; -- options.rtSettings.lensfunDbBundleDirectory = LENSFUN_DB_PATH; -- - #else -- argv0 = DATA_SEARCH_PATH; -- creditsPath = CREDITS_SEARCH_PATH; -- licensePath = LICENCE_SEARCH_PATH; -- options.rtSettings.lensfunDbDirectory = LENSFUN_DB_PATH; -- options.rtSettings.lensfunDbBundleDirectory = LENSFUN_DB_PATH; --#endif -+ app.setArgv0(DATA_SEARCH_PATH); -+ app.setCreditsPath(CREDITS_SEARCH_PATH); -+ app.setLicensePath(LICENCE_SEARCH_PATH); -+#endif // BUILD_BUNDLE -+ -+ app.mut_options().rtSettings.lensfunDbDirectory = LENSFUN_DB_PATH; -+ app.mut_options().rtSettings.lensfunDbBundleDirectory = LENSFUN_DB_PATH; - - #ifdef _WIN32 - bool consoleOpened = false; -@@ -422,7 +410,7 @@ int main (int argc, char **argv) - SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); - - if (argc > 1) { -- if (!remote && !Glib::file_test (argv1, Glib::FILE_TEST_EXISTS ) && !Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { -+ if (!app.isRemote() && !Glib::file_test (app.argv1(), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (app.argv1(), Glib::FILE_TEST_IS_DIR)) { - const bool stdoutRedirecttoConsole = (GetFileType (GetStdHandle (STD_OUTPUT_HANDLE)) == 0x0000); - // open console, if stdout is invalid - if (stdoutRedirecttoConsole) { -@@ -499,8 +487,8 @@ int main (int argc, char **argv) - fatalError = e.get_msg(); - } - -- if (gimpPlugin) { -- if (!Glib::file_test (argv1, Glib::FILE_TEST_EXISTS) || Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { -+ if (app.isGimpPlugin()) { -+ if (!Glib::file_test (app.argv1(), Glib::FILE_TEST_EXISTS) || Glib::file_test (app.argv1(), Glib::FILE_TEST_IS_DIR)) { - printf ("Error: argv1 doesn't exist\n"); - return 1; - } -@@ -509,8 +497,8 @@ int main (int argc, char **argv) - printf ("Error: -gimp requires two arguments\n"); - return 1; - } -- } else if (!remote && Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { -- simpleEditor = true; -+ } else if (!app.isRemote() && Glib::file_test(app.argv1(), Glib::FILE_TEST_EXISTS) && !Glib::file_test(app.argv1(), Glib::FILE_TEST_IS_DIR)) { -+ app.setIsSimpleEditor(true); - } - - int ret = 0; -@@ -519,13 +507,13 @@ int main (int argc, char **argv) - gdk_threads_init(); - gtk_init (&argc, &argv); // use the "--g-fatal-warnings" command line flag to make warnings fatal - -- if (fatalError.empty() && remote) { -- char *app_argv[2] = { const_cast (argv0.c_str()) }; -+ if (fatalError.empty() && app.isRemote()) { -+ char *app_argv[2] = { const_cast (app.argv0().c_str()) }; - int app_argc = 1; - -- if (!argv1.empty()) { -+ if (!app.argv1().empty()) { - app_argc = 2; -- app_argv[1] = const_cast (argv1.c_str()); -+ app_argv[1] = const_cast (app.argv1().c_str()); - } - - RTApplication app; -@@ -535,13 +523,13 @@ int main (int argc, char **argv) - Gtk::Main m (&argc, &argv); - gdk_threads_enter(); - const std::unique_ptr rtWindow (create_rt_window()); -- if (gimpPlugin) { -+ if (app.isGimpPlugin()) { - show_gimp_plugin_info_dialog(rtWindow.get()); - } - m.run (*rtWindow); - gdk_threads_leave(); - -- if (gimpPlugin && rtWindow->epanel && rtWindow->epanel->isRealized()) { -+ if (app.isGimpPlugin() && rtWindow->epanel && rtWindow->epanel->isRealized()) { - if (!rtWindow->epanel->saveImmediately(argv2, SaveFormat())) { - ret = -2; - } -diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc -index cdff5f70b..8307708e8 100644 ---- a/rtgui/navigator.cc -+++ b/rtgui/navigator.cc -@@ -27,17 +27,10 @@ - - using namespace rtengine; - --namespace --{ -- --const rtengine::procparams::ColorManagementParams DEFAULT_CMP; -- --} -- - Navigator::Navigator() : - pointer_moved_delayed_call(50, 100), -- currentRGBUnit(options.navRGBUnit), -- currentHSVUnit(options.navHSVUnit) -+ currentRGBUnit(App::get().options().navRGBUnit), -+ currentHSVUnit(App::get().options().navHSVUnit) - { - pointer_moved_delayed_call.setFunction( - [this](bool validPos, const rtengine::procparams::ColorManagementParams *cmp, int x, int y, int r, int g, int b, bool isRaw) -@@ -74,7 +67,7 @@ Navigator::Navigator() : - static_cast(g), - static_cast(b), - LAB_l, LAB_a, LAB_b, -- cmp != nullptr ? *cmp : DEFAULT_CMP, -+ cmp != nullptr ? *cmp : App::get().fallbackColorCmp(), - true); - LAB_l /= 327.68f; - LAB_a /= 327.68f; -@@ -356,7 +349,7 @@ void Navigator::cycleUnitsRGB (GdkEventButton *event) { - if (v == (uint16_t)Options::NavigatorUnit::_COUNT) { - v = 0; - } -- options.navRGBUnit = currentRGBUnit = (Options::NavigatorUnit)v; -+ App::get().mut_options().navRGBUnit = currentRGBUnit = (Options::NavigatorUnit)v; - - switch (currentRGBUnit) { - case Options::NavigatorUnit::R0_1: -@@ -385,7 +378,7 @@ void Navigator::cycleUnitsHSV (GdkEventButton *event) { - if (v == (uint16_t)Options::NavigatorUnit::_COUNT) { - v = 0; - } -- options.navHSVUnit = currentHSVUnit = (Options::NavigatorUnit)v; -+ App::get().mut_options().navHSVUnit = currentHSVUnit = (Options::NavigatorUnit)v; - - switch (currentHSVUnit) { - case Options::NavigatorUnit::R0_1: -diff --git a/rtgui/options.cc b/rtgui/options.cc -index 46d5f4edb..7e3d4127f 100644 ---- a/rtgui/options.cc -+++ b/rtgui/options.cc -@@ -56,10 +56,6 @@ Glib::ustring Options::rtdir; - // User's cached data directory - Glib::ustring Options::cacheBaseDir; - --Options options; --Glib::ustring versionString = RTVERSION; --Glib::ustring paramFileExtension = ".pp3"; -- - Options::Options() - { - -@@ -77,13 +73,13 @@ inline bool Options::checkProfilePath(Glib::ustring &path) - - Glib::ustring p = getUserProfilePath(); - -- if (!p.empty() && Glib::file_test(path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { -+ if (!p.empty() && Glib::file_test(path + App::PARAM_FILE_EXTENSION, Glib::FILE_TEST_EXISTS)) { - return true; - } - - p = getGlobalProfilePath(); - -- return !p.empty() && Glib::file_test(path + paramFileExtension, Glib::FILE_TEST_EXISTS); -+ return !p.empty() && Glib::file_test(path + App::PARAM_FILE_EXTENSION, Glib::FILE_TEST_EXISTS); - } - - bool Options::checkDirPath(Glib::ustring &path, Glib::ustring errString) -@@ -120,7 +116,7 @@ void Options::updatePaths() - - if (checkDirPath(profilePath, "Error: the user's processing profile path doesn't point to a directory or doesn't exist!\n")) { - userProfilePath = profilePath; -- tmpPath = Glib::build_filename(argv0, "profiles"); -+ tmpPath = Glib::build_filename(App::get().argv0(), "profiles"); - - if (checkDirPath(tmpPath, "Error: the global's processing profile path doesn't point to a directory or doesn't exist!\n")) { - if (userProfilePath != tmpPath) { -@@ -128,7 +124,7 @@ void Options::updatePaths() - } - } - } else { -- tmpPath = Glib::build_filename(argv0, "profiles"); -+ tmpPath = Glib::build_filename(App::get().argv0(), "profiles"); - - if (checkDirPath(tmpPath, "Error: the global's processing profile path doesn't point to a directory or doesn't exist!\n")) { - globalProfilePath = tmpPath; -@@ -151,7 +147,7 @@ void Options::updatePaths() - userProfilePath = tmpPath; - } - -- tmpPath = Glib::build_filename(argv0, "profiles"); -+ tmpPath = Glib::build_filename(App::get().argv0(), "profiles"); - - if (checkDirPath(tmpPath, "Error: the user's processing profile path doesn't point to a directory or doesn't exist!\n")) { - globalProfilePath = tmpPath; -@@ -226,7 +222,7 @@ void Options::updatePaths() - } - } - --Glib::ustring Options::getPreferredProfilePath() -+Glib::ustring Options::getPreferredProfilePath() const - { - if (!userProfilePath.empty()) { - return userProfilePath; -@@ -244,7 +240,7 @@ Glib::ustring Options::getPreferredProfilePath() - *@return Send back the absolute path of the given filename or "Neutral" if "Neutral" has been set to profName. Implementer will have - * to test for this particular value. If the absolute path is invalid (e.g. the file doesn't exist), it will return an empty string. - */ --Glib::ustring Options::findProfilePath(Glib::ustring &profName) -+Glib::ustring Options::findProfilePath(Glib::ustring &profName) const - { - if (profName.empty()) { - return ""; -@@ -263,7 +259,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) - if (p == "${U}") { - // the path starts by the User virtual path - p = getUserProfilePath(); -- Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); -+ Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + App::PARAM_FILE_EXTENSION); - - if (!p.empty() && Glib::file_test(fullPath, Glib::FILE_TEST_EXISTS)) { - return Glib::path_get_dirname(fullPath); -@@ -271,7 +267,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) - } else if (p == "${G}") { - // the path starts by the User virtual path - p = getGlobalProfilePath(); -- Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); -+ Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + App::PARAM_FILE_EXTENSION); - - if (!p.empty() && Glib::file_test(fullPath, Glib::FILE_TEST_EXISTS)) { - return Glib::path_get_dirname(fullPath); -@@ -279,7 +275,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) - } else { - // compatibility case -> convert the path to the new format - p = getUserProfilePath(); -- Glib::ustring fullPath = Glib::build_filename(p, profName + paramFileExtension); -+ Glib::ustring fullPath = Glib::build_filename(p, profName + App::PARAM_FILE_EXTENSION); - - if (!p.empty() && Glib::file_test(fullPath, Glib::FILE_TEST_EXISTS)) { - // update the profile path -@@ -288,7 +284,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) - } - - p = getGlobalProfilePath(); -- fullPath = Glib::build_filename(p, profName + paramFileExtension); -+ fullPath = Glib::build_filename(p, profName + App::PARAM_FILE_EXTENSION); - - if (!p.empty() && Glib::file_test(fullPath, Glib::FILE_TEST_EXISTS)) { - profName = Glib::build_filename("${G}", profName); -@@ -527,43 +523,6 @@ void Options::setDefaults() - ICCPC_copyright = Options::getICCProfileCopyright(); - ICCPC_appendParamsToDesc = false; - -- fastexport_bypass_sharpening = true; -- fastexport_bypass_sharpenEdge = true; -- fastexport_bypass_sharpenMicro = true; -- //fastexport_bypass_lumaDenoise = true; -- //fastexport_bypass_colorDenoise = true; -- fastexport_bypass_defringe = true; -- fastexport_bypass_dirpyrDenoise = true; -- fastexport_bypass_dirpyrequalizer = true; -- fastexport_bypass_wavelet = true; -- fastexport_raw_bayer_method = "fast"; -- //fastexport_bypass_raw_bayer_all_enhance = true; -- fastexport_bypass_raw_bayer_dcb_iterations = true; -- fastexport_bypass_raw_bayer_dcb_enhance = true; -- fastexport_bypass_raw_bayer_lmmse_iterations = true; -- fastexport_bypass_raw_bayer_linenoise = true; -- fastexport_bypass_raw_bayer_greenthresh = true; -- fastexport_raw_xtrans_method = "fast"; -- fastexport_bypass_raw_ccSteps = true; -- fastexport_bypass_raw_ca = true; -- fastexport_bypass_raw_df = true; -- fastexport_bypass_raw_ff = true; -- fastexport_icm_input_profile = "(camera)"; -- fastexport_icm_working_profile = "ProPhoto"; -- fastexport_icm_output_profile = options.rtSettings.srgb; -- fastexport_icm_outputIntent = rtengine::RI_RELATIVE; -- fastexport_icm_outputBPC = true; -- fastexport_resize_enabled = true; -- fastexport_resize_scale = 1; -- fastexport_resize_appliesTo = "Cropped area"; -- fastexport_resize_method = "Lanczos"; -- fastexport_resize_dataspec = 3; -- fastexport_resize_width = 900; -- fastexport_resize_height = 900; -- fastexport_resize_longedge = 900; -- fastexport_resize_shortedge = 900; -- fastexport_use_fast_pipeline = true; -- - clutsDir = "./cluts"; - - cutOverlayBrush = std::vector (4); -@@ -679,6 +638,45 @@ void Options::setDefaults() - // rtSettings.decaction =0.3; - // rtSettings.ciebadpixgauss=false; - rtSettings.rgbcurveslumamode_gamut = true; -+ -+ fastexport_bypass_sharpening = true; -+ fastexport_bypass_sharpenEdge = true; -+ fastexport_bypass_sharpenMicro = true; -+ //fastexport_bypass_lumaDenoise = true; -+ //fastexport_bypass_colorDenoise = true; -+ fastexport_bypass_defringe = true; -+ fastexport_bypass_dirpyrDenoise = true; -+ fastexport_bypass_dirpyrequalizer = true; -+ fastexport_bypass_wavelet = true; -+ fastexport_raw_bayer_method = "fast"; -+ //fastexport_bypass_raw_bayer_all_enhance = true; -+ fastexport_bypass_raw_bayer_dcb_iterations = true; -+ fastexport_bypass_raw_bayer_dcb_enhance = true; -+ fastexport_bypass_raw_bayer_lmmse_iterations = true; -+ fastexport_bypass_raw_bayer_linenoise = true; -+ fastexport_bypass_raw_bayer_greenthresh = true; -+ fastexport_raw_xtrans_method = "fast"; -+ fastexport_bypass_raw_ccSteps = true; -+ fastexport_bypass_raw_ca = true; -+ fastexport_bypass_raw_df = true; -+ fastexport_bypass_raw_ff = true; -+ fastexport_icm_input_profile = "(camera)"; -+ fastexport_icm_working_profile = "ProPhoto"; -+ // Must be set after options.rtSettings.srgb has already been initialized! -+ fastexport_icm_output_profile = rtSettings.srgb; -+ fastexport_icm_outputIntent = rtengine::RI_RELATIVE; -+ fastexport_icm_outputBPC = true; -+ fastexport_resize_enabled = true; -+ fastexport_resize_scale = 1; -+ fastexport_resize_appliesTo = "Cropped area"; -+ fastexport_resize_method = "Lanczos"; -+ fastexport_resize_dataspec = 3; -+ fastexport_resize_width = 900; -+ fastexport_resize_height = 900; -+ fastexport_resize_longedge = 900; -+ fastexport_resize_shortedge = 900; -+ fastexport_use_fast_pipeline = true; -+ - lastIccDir = rtSettings.iccDirectory; - lastDarkframeDir = rtSettings.darkFramesPath; - lastFlatfieldDir = rtSettings.flatFieldsPath; -@@ -969,7 +967,7 @@ void Options::readFromFile(Glib::ustring fname) - if (keyFile.has_key("External Editor", "GimpDir")) { - gimpDir = keyFile.get_string("External Editor", "GimpDir"); - } -- auto executable = Glib::build_filename(options.gimpDir, "bin", "gimp-win-remote"); -+ auto executable = Glib::build_filename(gimpDir, "bin", "gimp-win-remote"); - if (Glib::file_test(executable, Glib::FILE_TEST_IS_EXECUTABLE)) { - if (editorToSendTo == 1) { - externalEditorIndex = externalEditors.size(); -@@ -2375,7 +2373,7 @@ void Options::readFromFile(Glib::ustring fname) - } catch (Glib::Error &err) { - Glib::ustring msg = Glib::ustring::compose("Options::readFromFile / Error code %1 while reading values from \"%2\":\n%3", err.code(), fname, err.what()); - -- if (options.rtSettings.verbose) { -+ if (App::get().options().rtSettings.verbose) { - printf("%s\n", msg.c_str()); - } - -@@ -2383,7 +2381,7 @@ void Options::readFromFile(Glib::ustring fname) - } catch (...) { - Glib::ustring msg = Glib::ustring::compose("Options::readFromFile / Unknown exception while trying to load \"%1\"!", fname); - -- if (options.rtSettings.verbose) { -+ if (App::get().options().rtSettings.verbose) { - printf("%s\n", msg.c_str()); - } - -@@ -2873,7 +2871,6 @@ void Options::saveToFile(Glib::ustring fname) - - void Options::load(bool lightweight) - { -- - // Find the application data path - - const gchar* path; -@@ -2908,22 +2905,23 @@ void Options::load(bool lightweight) - #endif - } - -+ auto& options = App::get().mut_options(); - if (options.rtSettings.verbose) { - printf("Settings directory (rtdir) = %s\n", rtdir.c_str()); - } - - // Set the cache folder in RT's base folder -- cacheBaseDir = Glib::build_filename(argv0, "mycache"); -+ cacheBaseDir = Glib::build_filename(App::get().argv0(), "mycache"); - - // Read the global option file (the one located in the application's base folder) - try { -- options.readFromFile(Glib::build_filename(argv0, "options")); -+ options.readFromFile(Glib::build_filename(App::get().argv0(), "options")); - } catch (Options::Error &) { - // ignore errors here - } - - if (!options.multiUser && path == nullptr) { -- rtdir = Glib::build_filename(argv0, "mysettings"); -+ rtdir = Glib::build_filename(App::get().argv0(), "mysettings"); - } - - // Modify the path of the cache folder to the one provided in RT_CACHE environment variable. -@@ -3039,7 +3037,7 @@ void Options::load(bool lightweight) - // out which are the parent translations. Furthermore, there must be a file for each locale () -- you cannot have - // 'French (CA)' unless there is a file 'French'. - -- Glib::ustring defaultTranslation = Glib::build_filename(argv0, "languages", "default"); -+ Glib::ustring defaultTranslation = Glib::build_filename(App::get().argv0(), "languages", "default"); - Glib::ustring languageTranslation = ""; - Glib::ustring localeTranslation = ""; - -@@ -3051,29 +3049,29 @@ void Options::load(bool lightweight) - std::vector langPortions = Glib::Regex::split_simple(" ", options.language); - - if (langPortions.size() >= 1) { -- languageTranslation = Glib::build_filename(argv0, "languages", langPortions.at(0)); -+ languageTranslation = Glib::build_filename(App::get().argv0(), "languages", langPortions.at(0)); - } - - if (langPortions.size() >= 2) { -- localeTranslation = Glib::build_filename(argv0, "languages", options.language); -+ localeTranslation = Glib::build_filename(App::get().argv0(), "languages", options.language); - } - } - - langMgr.load(options.language, {localeTranslation, languageTranslation, defaultTranslation}); - -- rtengine::init(&options.rtSettings, argv0, rtdir, !lightweight); -+ rtengine::init(&options.rtSettings, App::get().argv0(), rtdir, !lightweight); - } - - void Options::save() - { - -- options.saveToFile(Glib::build_filename(rtdir, "options")); -+ App::get().mut_options().saveToFile(Glib::build_filename(rtdir, "options")); - } - - /* - * return true if ext is a parsed extension (retained or not) - */ --bool Options::is_parse_extention(Glib::ustring fname) -+bool Options::is_parse_extention(Glib::ustring fname) const - { - Glib::ustring ext = getExtension(fname).lowercase(); - -@@ -3094,14 +3092,14 @@ bool Options::is_parse_extention(Glib::ustring fname) - /* - * return true if fname ends with one of the retained image file extensions - */ --bool Options::has_retained_extention(const Glib::ustring& fname) -+bool Options::has_retained_extention(const Glib::ustring& fname) const - { - return parsedExtensionsSet.find(getExtension(fname).lowercase()) != parsedExtensionsSet.end(); - } - - // Pattern matches "5.1" from "5.1-23-g12345678", when comparing option.version to RTVERSION --bool Options::is_new_version() { -- const std::string vs[] = {versionString, version}; -+bool Options::is_new_version() const { -+ const std::string vs[] = {App::VERSION, version}; - std::vector vMajor; - - for (const auto& v : vs) { -@@ -3114,26 +3112,26 @@ bool Options::is_new_version() { - /* - * return true if ext is an enabled extension - */ --bool Options::is_extention_enabled(const Glib::ustring& ext) -+bool Options::is_extention_enabled(const Glib::ustring& ext) const - { - return parsedExtensionsSet.find(ext.lowercase()) != parsedExtensionsSet.end(); - } - --Glib::ustring Options::getUserProfilePath() -+Glib::ustring Options::getUserProfilePath() const - { - return userProfilePath; - } - --Glib::ustring Options::getGlobalProfilePath() -+Glib::ustring Options::getGlobalProfilePath() const - { - return globalProfilePath; - } - --bool Options::is_defProfRawMissing() -+bool Options::is_defProfRawMissing() const - { - return defProfError & rtengine::toUnderlying(DefProfError::defProfRawMissing); - } --bool Options::is_defProfImgMissing() -+bool Options::is_defProfImgMissing() const - { - return defProfError & rtengine::toUnderlying(DefProfError::defProfImgMissing); - } -@@ -3153,11 +3151,11 @@ void Options::setDefProfImgMissing(bool value) - defProfError &= ~rtengine::toUnderlying(DefProfError::defProfImgMissing); - } - } --bool Options::is_bundledDefProfRawMissing() -+bool Options::is_bundledDefProfRawMissing() const - { - return defProfError & rtengine::toUnderlying(DefProfError::bundledDefProfRawMissing); - } --bool Options::is_bundledDefProfImgMissing() -+bool Options::is_bundledDefProfImgMissing() const - { - return defProfError & rtengine::toUnderlying(DefProfError::bundledDefProfImgMissing); - } -diff --git a/rtgui/options.h b/rtgui/options.h -index 0abed72df..e13bf661d 100644 ---- a/rtgui/options.h -+++ b/rtgui/options.h -@@ -29,6 +29,7 @@ - #else - #include - #endif -+#include "rtengine/rtapp.h" - #include "rtengine/settings.h" - #include - -@@ -532,30 +533,21 @@ public: - static void save(); - - // if multiUser=false, send back the global profile path -- Glib::ustring getPreferredProfilePath(); -- Glib::ustring getUserProfilePath(); -- Glib::ustring getGlobalProfilePath(); -- Glib::ustring findProfilePath (Glib::ustring &profName); -- bool is_parse_extention (Glib::ustring fname); -- bool has_retained_extention (const Glib::ustring& fname); -- bool is_new_version(); -- bool is_extention_enabled (const Glib::ustring& ext); -- bool is_defProfRawMissing(); -- bool is_bundledDefProfRawMissing(); -- bool is_defProfImgMissing(); -- bool is_bundledDefProfImgMissing(); -+ Glib::ustring getPreferredProfilePath() const; -+ Glib::ustring getUserProfilePath() const; -+ Glib::ustring getGlobalProfilePath() const; -+ Glib::ustring findProfilePath (Glib::ustring &profName) const; -+ bool is_parse_extention (Glib::ustring fname) const; -+ bool has_retained_extention (const Glib::ustring& fname) const; -+ bool is_new_version() const; -+ bool is_extention_enabled (const Glib::ustring& ext) const; -+ bool is_defProfRawMissing() const; -+ bool is_bundledDefProfRawMissing() const; -+ bool is_defProfImgMissing() const; -+ bool is_bundledDefProfImgMissing() const; - void setDefProfRawMissing (bool value); - void setBundledDefProfRawMissing (bool value); - void setDefProfImgMissing (bool value); - void setBundledDefProfImgMissing (bool value); - static Glib::ustring getICCProfileCopyright(); - }; -- --extern Options options; --extern Glib::ustring argv0; --extern Glib::ustring argv1; --extern bool simpleEditor; --extern bool gimpPlugin; --extern bool remote; --extern Glib::ustring versionString; --extern Glib::ustring paramFileExtension; -diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc -index a5e5ae12e..028f64918 100644 ---- a/rtgui/paramsedited.cc -+++ b/rtgui/paramsedited.cc -@@ -84,6 +84,8 @@ void initFrom(FramingParamsEdited& edits, const ProcParams& params, const ProcPa - void combine(FramingParams& toEdit, const FramingParams& mod, const FramingParamsEdited& edits, - bool dontForceSet) - { -+ const auto& options = App::get().options(); -+ - if (edits.enabled) { - toEdit.enabled = mod.enabled; - } -@@ -2469,6 +2471,7 @@ void ParamsEdited::initFrom(const std::vector& - - void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods, bool forceSet) - { -+ const Options& options = App::get().options(); - - bool dontforceSet = !forceSet; - -diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc -index 504644378..397b88d01 100644 ---- a/rtgui/pdsharpening.cc -+++ b/rtgui/pdsharpening.cc -@@ -83,6 +83,7 @@ PdSharpening::PdSharpening() : - dradiusOffset->setAdjusterListener(this); - diter->setAdjusterListener(this); - -+ const auto& options = App::get().options(); - contrast->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - dradius->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - dradiusOffset->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); -diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc -index 1f7a47f15..d83680483 100644 ---- a/rtgui/placesbrowser.cc -+++ b/rtgui/placesbrowser.cc -@@ -106,6 +106,7 @@ void PlacesBrowser::refreshPlacesList () - { - placesModel->clear (); - -+ const auto& options = App::get().options(); - // append favorites - for (size_t i = 0; i < options.favoriteDirs.size(); i++) { - Glib::RefPtr fav = Gio::File::create_for_path (options.favoriteDirs[i]); -@@ -314,6 +315,7 @@ void PlacesBrowser::addPressed () - return; - } - -+ auto& options = App::get().mut_options(); - // check if the dirname is already in the list. If yes, return. - for (size_t i = 0; i < options.favoriteDirs.size(); i++) - if (options.favoriteDirs[i] == lastSelectedDir) { -@@ -340,6 +342,7 @@ void PlacesBrowser::delPressed () - Glib::RefPtr selection = treeView->get_selection(); - Gtk::TreeModel::iterator iter = selection->get_selected(); - -+ auto& options = App::get().mut_options(); - if (iter && iter->get_value (placesColumns.type) == 5) { - std::vector::iterator i = std::find (options.favoriteDirs.begin(), options.favoriteDirs.end(), iter->get_value (placesColumns.root)); - -diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc -index 3cc003bb0..28e67da5a 100644 ---- a/rtgui/preferences.cc -+++ b/rtgui/preferences.cc -@@ -60,7 +60,6 @@ void placeSpinBox(Gtk::Container* where, Gtk::SpinButton* &spin, const std::stri - } - } - --extern Glib::ustring argv0; - Glib::RefPtr themecss; - Glib::RefPtr fontcss; - -@@ -76,8 +75,8 @@ Preferences::Preferences(RTWindow *rtwindow) - , toolLocationPreference(nullptr) - , swFavorites(nullptr) - { -- -- moptions.copyFrom(&options); -+ const auto& options = App::get().options(); -+ moptions.copyFrom(&App::get().mut_options()); - - set_size_request(650, -1); - set_default_size(options.preferencesWidth, options.preferencesHeight); -@@ -145,8 +144,8 @@ Preferences::Preferences(RTWindow *rtwindow) - - Preferences::~Preferences() - { -- - ProfileStore::getInstance()->removeListener(this); -+ auto& options = App::get().mut_options(); - get_size(options.preferencesWidth, options.preferencesHeight); - } - -@@ -1228,11 +1227,11 @@ Gtk::Widget* Preferences::getGeneralPanel() - setExpandAlignProperties(languages, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - - std::vector langs; -- parseDir(argv0 + "/languages", langs, ""); -+ parseDir(App::get().argv0() + "/languages", langs, ""); - - for (const auto &lang : langs) { - if ("default" != lang && "README" != lang && "LICENSE" != lang) { -- auto lang_metadata = langMgr.getMetadata(Glib::build_filename(argv0 + "/languages", lang)); -+ auto lang_metadata = langMgr.getMetadata(Glib::build_filename(App::get().argv0() + "/languages", lang)); - const auto &display_name = - lang_metadata != nullptr - ? Glib::ustring(lang_metadata->getLanguageName(lang)) -@@ -1265,7 +1264,7 @@ Gtk::Widget* Preferences::getGeneralPanel() - - themeCBT = Gtk::manage(new Gtk::ComboBoxText()); - themeCBT->set_active(0); -- parseThemeDir(Glib::build_filename(argv0, "themes")); -+ parseThemeDir(Glib::build_filename(App::get().argv0(), "themes")); - for (size_t i = 0; i < themeNames.size(); i++) { - themeCBT->append(themeNames.at(i)); - } -@@ -1273,6 +1272,7 @@ Gtk::Widget* Preferences::getGeneralPanel() - Gtk::Label* mainFontLbl = Gtk::manage(new Gtk::Label(M("PREFERENCES_APPEARANCE_MAINFONT"))); - setExpandAlignProperties(mainFontLbl, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - -+ const auto& options = App::get().options(); - mainFontFB = Gtk::manage(new Gtk::FontButton()); - mainFontFB->set_use_size(true); - if (options.fontFamily == "default") { -@@ -2172,6 +2172,7 @@ void Preferences::fillPreferences() - navGuideColorCB->set_rgba (NavGuideCol); - navGuideColorCB->set_alpha ( (unsigned short) (moptions.navGuideBrush[3] * 65535.0)); - -+ const auto& options = App::get().options(); - if (options.fontFamily == "default") { - mainFontFB->set_font_name (Glib::ustring::compose ("%1, %2", initialFontFamily, initialFontSize)); - } else { -@@ -2389,7 +2390,7 @@ void Preferences::langAutoDetectToggled() - - void Preferences::okPressed() - { -- -+ auto& options = App::get().mut_options(); - storePreferences(); - workflowUpdate(); - options.copyFrom(&moptions); -@@ -2408,6 +2409,7 @@ void Preferences::okPressed() - - void Preferences::cancelPressed() - { -+ auto& options = App::get().mut_options(); - // set the initial theme back - if (themeNames.at (themeCBT->get_active_row_number ()) != options.theme) { - switchThemeTo(options.theme); -@@ -2508,6 +2510,7 @@ void Preferences::bundledProfilesChanged() - rpconn.block(true); - ipconn.block(true); - -+ auto& options = App::get().mut_options(); - // parseProfiles does use options.useBundledProfiles, so we temporarily change its value - bool currValue = options.useBundledProfiles; - options.useBundledProfiles = useBundledProfiles->get_active(); -@@ -2581,7 +2584,7 @@ void Preferences::restoreValue() - void Preferences::switchThemeTo(Glib::ustring newTheme) - { - -- Glib::ustring filename(Glib::build_filename(argv0, "themes", newTheme + ".css")); -+ Glib::ustring filename(Glib::build_filename(App::get().argv0(), "themes", newTheme + ".css")); - - if (!themecss) { - themecss = Gtk::CssProvider::create(); -@@ -2635,6 +2638,7 @@ void Preferences::switchFontTo(const Glib::ustring &newFontFamily, const int new - - void Preferences::workflowUpdate() - { -+ const auto& options = App::get().options(); - - if (moptions.tabbedUI != options.tabbedUI) { - parent->setEditorMode(moptions.tabbedUI); -diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc -index 507ce6681..444a868c9 100644 ---- a/rtgui/preprocess.cc -+++ b/rtgui/preprocess.cc -@@ -30,7 +30,7 @@ using namespace rtengine::procparams; - - const Glib::ustring PreProcess::TOOL_NAME = "preprocess"; - --PreProcess::PreProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar) -+PreProcess::PreProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), App::get().options().prevdemo != PD_Sidecar) - { - - Gtk::Box* hotdeadPixel = Gtk::manage( new Gtk::Box () ); -@@ -48,6 +48,7 @@ PreProcess::PreProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_ - hdThreshold->set_tooltip_markup (M("TP_RAW_HD_TOOLTIP")); - hdThreshold->setAdjusterListener (this); - -+ const auto& options = App::get().options(); - hdThreshold->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - hdThreshold->show(); -diff --git a/rtgui/previewmodepanel.cc b/rtgui/previewmodepanel.cc -index 25167ae3b..6729dd3ff 100644 ---- a/rtgui/previewmodepanel.cc -+++ b/rtgui/previewmodepanel.cc -@@ -33,6 +33,7 @@ PreviewModePanel::PreviewModePanel (ImageArea* ia) : - nBC2("square-toggle-white-on-narrow"), ngBC2("square-toggle-white-off-narrow"), - nBC3("square-toggle-gray-on-narrow"), ngBC3("square-toggle-gray-off-narrow") - { -+ const auto& options = App::get().options(); - backColor0 = Gtk::manage (new Gtk::ToggleButton ()); - backColor0->get_style_context()->add_class("narrowbutton"); - backColor0->set_relief(Gtk::RELIEF_NONE); -diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc -index 92bb71a78..01ac638d5 100644 ---- a/rtgui/previewwindow.cc -+++ b/rtgui/previewwindow.cc -@@ -91,6 +91,7 @@ void PreviewWindow::updatePreviewImage () - - if (previewHandler->getCropParams().enabled) { - rtengine::procparams::CropParams cparams = previewHandler->getCropParams(); -+ const auto& options = App::get().options(); - switch (options.cropGuides) { - case Options::CROP_GUIDE_NONE: - cparams.guide = rtengine::procparams::CropParams::Guide::NONE; -@@ -169,6 +170,7 @@ bool PreviewWindow::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) - cr->rectangle (rectX + 1. * s, rectY + 1. * s, rectW - 2. * s, rectH - 2. * s); - cr->stroke (); - -+ const auto& options = App::get().options(); - // draw a "frame" line. Color of frame line can be set in preferences - cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); - cr->rectangle (rectX, rectY, rectW, rectH); -diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc -index 1bb567cb3..2303a2653 100644 ---- a/rtgui/profilepanel.cc -+++ b/rtgui/profilepanel.cc -@@ -47,13 +47,13 @@ void ProfilePanel::cleanup () - - ProfilePanel::ProfilePanel () : storedPProfile(nullptr), - modeOn("profile-filled"), modeOff("profile-partial"), -- profileFillImage(Gtk::manage(new RTImage(options.filledProfile ? modeOn : modeOff, Gtk::ICON_SIZE_LARGE_TOOLBAR))), -+ profileFillImage(Gtk::manage(new RTImage(App::get().options().filledProfile ? modeOn : modeOff, Gtk::ICON_SIZE_LARGE_TOOLBAR))), - lastSavedPSE(nullptr), customPSE(nullptr) - { - tpc = nullptr; - - fillMode = Gtk::manage (new Gtk::ToggleButton()); -- fillMode->set_active(options.filledProfile); -+ fillMode->set_active(App::get().options().filledProfile); - fillMode->add(*profileFillImage); - fillMode->signal_toggled().connect ( sigc::mem_fun(*this, &ProfilePanel::profileFillModeToggled) ); - fillMode->set_tooltip_text(M("PROFILEPANEL_MODE_TOOLTIP")); -@@ -311,6 +311,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) - } - } - -+ auto& options = App::get().mut_options(); - Gtk::FileChooserDialog dialog(getToplevelWindow(this), M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); - bindCurrentFolder(dialog, options.loadSaveProfilePath); - dialog.set_current_name(lastFilename); -@@ -332,7 +333,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) - //Add filters, so that only certain file types can be selected: - auto filter_pp = Gtk::FileFilter::create(); - filter_pp->set_name(M("FILECHOOSER_FILTER_PP")); -- filter_pp->add_pattern("*" + paramFileExtension); -+ filter_pp->add_pattern("*" + App::PARAM_FILE_EXTENSION); - dialog.add_filter(filter_pp); - - auto filter_any = Gtk::FileFilter::create(); -@@ -354,8 +355,8 @@ void ProfilePanel::save_clicked (GdkEventButton* event) - - auto fname = dialog.get_filename(); - -- if (("." + getExtension(fname)) != paramFileExtension) { -- fname += paramFileExtension; -+ if (("." + getExtension(fname)) != App::PARAM_FILE_EXTENSION) { -+ fname += App::PARAM_FILE_EXTENSION; - } - - if (!confirmOverwrite(dialog, fname)) { -@@ -467,6 +468,7 @@ void ProfilePanel::load_clicked (GdkEventButton* event) - } - - Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); -+ auto& options = App::get().mut_options(); - bindCurrentFolder (dialog, options.loadSaveProfilePath); - - //Add the user's default (or global if multiuser=false) profile path to the Shortcut list -@@ -486,7 +488,7 @@ void ProfilePanel::load_clicked (GdkEventButton* event) - //Add filters, so that only certain file types can be selected: - Glib::RefPtr filter_pp = Gtk::FileFilter::create(); - filter_pp->set_name(M("FILECHOOSER_FILTER_PP")); -- filter_pp->add_pattern("*" + paramFileExtension); -+ filter_pp->add_pattern("*" + App::PARAM_FILE_EXTENSION); - dialog.add_filter(filter_pp); - - Glib::RefPtr filter_any = Gtk::FileFilter::create(); -@@ -903,7 +905,7 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams - - void ProfilePanel::setInitialFileName (const Glib::ustring& filename) - { -- lastFilename = Glib::path_get_basename(filename) + paramFileExtension; -+ lastFilename = Glib::path_get_basename(filename) + App::PARAM_FILE_EXTENSION; - imagePath = Glib::path_get_dirname(filename); - } - -@@ -920,6 +922,6 @@ void ProfilePanel::profileFillModeToggled() - - void ProfilePanel::writeOptions() - { -- options.filledProfile = fillMode->get_active(); -+ App::get().mut_options().filledProfile = fillMode->get_active(); - } - -diff --git a/rtgui/profilestorecombobox.cc b/rtgui/profilestorecombobox.cc -index 0eaf082d2..c7f99d853 100644 ---- a/rtgui/profilestorecombobox.cc -+++ b/rtgui/profilestorecombobox.cc -@@ -69,7 +69,7 @@ void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, - if (entry->type == PSET_FOLDER) { - Glib::ustring folderPath ( ProfileStore::getInstance()->getPathFromId (entry->folderId) ); - -- if (options.useBundledProfiles || ((folderPath != "${G}" ) && (folderPath != "${U}" ))) { -+ if (App::get().options().useBundledProfiles || ((folderPath != "${G}" ) && (folderPath != "${U}" ))) { - // creating the new submenu - Gtk::TreeModel::Row newSubMenu; - -diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc -index 2288c1b2f..d2fd7ef3e 100644 ---- a/rtgui/rawcacorrection.cc -+++ b/rtgui/rawcacorrection.cc -@@ -49,6 +49,7 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAWCACORR_LAB - caAutoiterations->setAdjusterListener (this); - caAutoiterations->set_tooltip_markup(M("TP_RAWCACORR_AUTOIT_TOOLTIP")); - -+ const auto& options = App::get().options(); - caAutoiterations->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"), -4.0, 4.0, 0.1, 0, icaredL, icaredR)); -diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc -index 26f2dba74..b970f0af2 100644 ---- a/rtgui/rawexposure.cc -+++ b/rtgui/rawexposure.cc -@@ -35,6 +35,7 @@ RAWExposure::RAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_WHI - PexPos = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_LINEAR"), 0.1, 16.0, 0.01, 1)); - PexPos->setAdjusterListener (this); - -+ const auto& options = App::get().options(); - PexPos->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - PexPos->show(); -diff --git a/rtgui/recentbrowser.cc b/rtgui/recentbrowser.cc -index 9d3cc1f12..971b190bc 100644 ---- a/rtgui/recentbrowser.cc -+++ b/rtgui/recentbrowser.cc -@@ -32,6 +32,7 @@ RecentBrowser::RecentBrowser () - frame->set_label_align(0.025, 0.5); - frame->add (*recentDirs); - -+ const auto& options = App::get().options(); - for(size_t i = 0; i < options.recentFolders.size(); i++) { - recentDirs->append (options.recentFolders[i]); - } -@@ -55,7 +56,7 @@ void RecentBrowser::selectionChanged () - - void RecentBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) - { -- -+ auto& options = App::get().mut_options(); - ssize_t numFolders = options.recentFolders.size(); - ssize_t i = -1; - -diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc -index 73b5e819c..0702632e7 100644 ---- a/rtgui/retinex.cc -+++ b/rtgui/retinex.cc -@@ -162,6 +162,8 @@ Retinex::Retinex () : FoldableToolPanel (this, TOOL_NAME, M ("TP_RETINEX_LABEL") - maskGrid->attach (*mapgrid, 0, 0, 1, 1); - mapgrid->show(); - -+ auto& options = App::get().mut_options(); -+ - // Map Equalizer - curveEditormap = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_CONTEDIT_MAP")); - setExpandAlignProperties (curveEditormap, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); -diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc -index c8b51b70b..c263d27d6 100644 ---- a/rtgui/rgbcurves.cc -+++ b/rtgui/rgbcurves.cc -@@ -46,6 +46,7 @@ RGBCurves::RGBCurves () : FoldableToolPanel(this, TOOL_NAME, M("TP_RGBCURVES_LAB - - std::vector milestones; - -+ auto& options = App::get().mut_options(); - curveEditorG = new CurveEditorGroup (options.lastRgbCurvesDir, M("TP_RGBCURVES_CHANNEL")); - curveEditorG->setCurveListener (this); - -diff --git a/rtgui/rtscalable.cc b/rtgui/rtscalable.cc -index bb2991c51..bfbf7b2fb 100644 ---- a/rtgui/rtscalable.cc -+++ b/rtgui/rtscalable.cc -@@ -23,11 +23,10 @@ - #include - #include - -+#include "rtengine/rtapp.h" - #include "rtengine/settings.h" - #include "guiutils.h" - --extern Glib::ustring argv0; -- - // Default static parameter values - double RTScalable::dpi = 96.; - int RTScalable::scale = 1; -@@ -119,7 +118,7 @@ Cairo::RefPtr RTScalable::loadSurfaceFromPNG(const Glib::us - path = fname; - } else { - // Look for PNG file in "images" folder -- Glib::ustring imagesFolder = Glib::build_filename(argv0, "images"); -+ Glib::ustring imagesFolder = Glib::build_filename(App::get().argv0(), "images"); - path = Glib::build_filename(imagesFolder, fname); - } - -@@ -146,7 +145,7 @@ Cairo::RefPtr RTScalable::loadSurfaceFromSVG(const Glib::us - path = fname; - } else { - // Look for SVG file in "images" folder -- Glib::ustring imagesFolder = Glib::build_filename(argv0, "images"); -+ Glib::ustring imagesFolder = Glib::build_filename(App::get().argv0(), "images"); - path = Glib::build_filename(imagesFolder, fname); - } - -diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc -index 8ecaa1184..84f562b3e 100755 ---- a/rtgui/rtwindow.cc -+++ b/rtgui/rtwindow.cc -@@ -74,7 +74,7 @@ osx_open_file_cb (GtkosxApplication *app, gchar *path_, gpointer data) - { - RTWindow *rtWin = static_cast(data); - -- if (!argv1.empty()) { -+ if (!App::get().argv1().empty()) { - // skip handling if we have a file argument or else we get double open of same file - return false; - } -@@ -107,6 +107,7 @@ RTWindow::RTWindow () - // ------- loading theme files - - Glib::RefPtr screen = Gdk::Screen::get_default(); -+ auto& options = App::get().mut_options(); - - if (screen) { - // Setting default theme and icon theme (bases for custom themes) -@@ -119,10 +120,10 @@ RTWindow::RTWindow () - - // Look for theme and set it - // Check if the current theme name in options exists, otherwise set it to default one (i.e. "RawTherapee.css") -- auto filename = Glib::build_filename(argv0, "themes", options.theme + ".css"); -+ auto filename = Glib::build_filename(App::get().argv0(), "themes", options.theme + ".css"); - if (!Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - options.theme = "RawTherapee"; -- filename = Glib::build_filename(argv0, "themes", options.theme + ".css"); -+ filename = Glib::build_filename(App::get().argv0(), "themes", options.theme + ".css"); - } - - cssRT = Gtk::CssProvider::create(); -@@ -214,7 +215,7 @@ RTWindow::RTWindow () - gtkosx_application_ready (osxApp); - } - #endif -- versionStr = "RawTherapee " + versionString; -+ versionStr = "RawTherapee " + App::VERSION; - - set_title_decorated (""); - set_resizable (true); -@@ -231,7 +232,7 @@ RTWindow::RTWindow () - signal_key_press_event().connect ( sigc::mem_fun (*this, &RTWindow::keyPressed) ); - signal_key_release_event().connect(sigc::mem_fun(*this, &RTWindow::keyReleased)); - -- if (simpleEditor) { -+ if (App::get().isSimpleEditor()) { - epanel = Gtk::manage ( new EditorPanel (nullptr) ); - epanel->setParent (this); - epanel->setParentWindow (this); -@@ -241,11 +242,11 @@ RTWindow::RTWindow () - pldBridge = nullptr; // No progress listener - - CacheManager* cm = CacheManager::getInstance(); -- Thumbnail* thm = cm->getEntry ( argv1 ); -+ Thumbnail* thm = cm->getEntry ( App::get().argv1() ); - - if (thm) { - int error; -- rtengine::InitialImage *ii = rtengine::InitialImage::load (argv1, thm->getType() == FT_Raw, &error, nullptr); -+ rtengine::InitialImage *ii = rtengine::InitialImage::load (App::get().argv1(), thm->getType() == FT_Raw, &error, nullptr); - epanel->open ( thm, ii ); - } - } else { -@@ -372,8 +373,8 @@ RTWindow::RTWindow () - - bpanel->init (this); - -- if (!argv1.empty() && !remote) { -- Thumbnail* thm = cacheMgr->getEntry (argv1); -+ if (!App::get().argv1().empty() && !App::get().isRemote()) { -+ Thumbnail* thm = cacheMgr->getEntry (App::get().argv1()); - - if (thm) { - fpanel->fileCatalog->openRequested ({thm}); -@@ -384,7 +385,7 @@ RTWindow::RTWindow () - - RTWindow::~RTWindow() - { -- if (!simpleEditor) { -+ if (!App::get().isSimpleEditor()) { - delete pldBridge; - } - -@@ -406,7 +407,7 @@ void RTWindow::on_realize () - fpanel->setAspect(); - } - -- if (simpleEditor) { -+ if (App::get().isSimpleEditor()) { - epanel->setAspect(); - } - -@@ -414,9 +415,10 @@ void RTWindow::on_realize () - - // Display release notes only if new major version. - bool waitForSplash = false; -+ auto& options = App::get().mut_options(); - if (options.is_new_version()) { - // Update the version parameter with the right value -- options.version = versionString; -+ options.version = App::VERSION; - - splash = new Splash (*this); - splash->set_transient_for (*this); -@@ -439,6 +441,7 @@ void RTWindow::on_realize () - - void RTWindow::showErrors() - { -+ auto& options = App::get().mut_options(); - // alerting users if the default raw and image profiles are missing - if (options.is_defProfRawMissing()) { - options.defProfRaw = DEFPROFILE_RAW; -@@ -465,6 +468,7 @@ void RTWindow::showErrors() - - bool RTWindow::on_configure_event (GdkEventConfigure* event) - { -+ auto& options = App::get().mut_options(); - if (!options.windowMaximized && !is_fullscreen && !is_minimized) { - get_size (options.windowWidth, options.windowHeight); - get_position (options.windowX, options.windowY); -@@ -479,7 +483,7 @@ bool RTWindow::on_configure_event (GdkEventConfigure* event) - bool RTWindow::on_window_state_event (GdkEventWindowState* event) - { - // Retrieve RT window states -- options.windowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; -+ App::get().mut_options().windowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; - is_minimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED; - is_fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; - -@@ -519,7 +523,7 @@ void RTWindow::on_mainNB_switch_page (Gtk::Widget* widget, guint page_num) - - void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) - { -- if (options.multiDisplayMode > 0) { -+ if (App::get().options().multiDisplayMode > 0) { - EditWindow * wndEdit = EditWindow::getInstance (this); - wndEdit->addEditorPanel (ep, name); - wndEdit->show_all(); -@@ -573,7 +577,7 @@ void RTWindow::remEditorPanel (EditorPanel* ep) - return; // Will crash if destroyed while loading - } - -- if (options.multiDisplayMode > 0) { -+ if (App::get().options().multiDisplayMode > 0) { - EditWindow * wndEdit = EditWindow::getInstance (this); - wndEdit->remEditorPanel (ep); - } else { -@@ -602,7 +606,7 @@ void RTWindow::remEditorPanel (EditorPanel* ep) - - bool RTWindow::selectEditorPanel (const std::string &name) - { -- if (options.multiDisplayMode > 0) { -+ if (App::get().options().multiDisplayMode > 0) { - EditWindow * wndEdit = EditWindow::getInstance (this); - - if (wndEdit->selectEditorPanel (name)) { -@@ -658,7 +662,7 @@ bool RTWindow::keyPressed (GdkEventKey* event) - toggle_fullscreen(); - } - -- if (simpleEditor) -+ if (App::get().isSimpleEditor()) - // in simpleEditor mode, there's no other tab that can handle pressed keys, so we can send the event to editor panel then return - { - return epanel->handleShortcutKey (event); -@@ -739,8 +743,9 @@ bool RTWindow::on_delete_event (GdkEventAny* event) - // Check if any editor is still processing, and do NOT quit if so. Otherwise crashes and inconsistent caches - bool isProcessing = false; - EditWindow* editWindow = nullptr; -+ auto& options = App::get().mut_options(); - -- if (isSingleTabMode() || simpleEditor) { -+ if (isSingleTabMode() || App::get().isSimpleEditor()) { - isProcessing = epanel->getIsProcessing(); - } else if (options.multiDisplayMode > 0) { - editWindow = EditWindow::getInstance (this); -@@ -767,7 +772,7 @@ bool RTWindow::on_delete_event (GdkEventAny* event) - bpanel->saveOptions (); - } - -- if ((isSingleTabMode() || simpleEditor) && epanel->isRealized()) { -+ if ((isSingleTabMode() || App::get().isSimpleEditor()) && epanel->isRealized()) { - epanel->saveProfile(); - epanel->writeOptions (); - } else { -@@ -840,7 +845,7 @@ bool RTWindow::on_delete_event (GdkEventAny* event) - - void RTWindow::writeToolExpandedStatus (std::vector &tpOpen) - { -- if ((isSingleTabMode() || gimpPlugin) && epanel->isRealized()) { -+ if ((isSingleTabMode() || App::get().isGimpPlugin()) && epanel->isRealized()) { - epanel->writeToolExpandedStatus (tpOpen); - } else { - // Storing the options of the last EditorPanel before Gtk destroys everything -@@ -881,6 +886,7 @@ void RTWindow::showICCProfileCreator () - - fpanel->optionsChanged (); - -+ const auto& options = App::get().options(); - if (epanel) { - epanel->defaultMonitorProfileChanged (options.rtSettings.monitorProfile, options.rtSettings.autoMonitorProfile); - } -@@ -898,6 +904,7 @@ void RTWindow::showPreferences () - - fpanel->optionsChanged (); - -+ const auto& options = App::get().options(); - if (epanel) { - epanel->defaultMonitorProfileChanged (options.rtSettings.monitorProfile, options.rtSettings.autoMonitorProfile); - } -@@ -914,7 +921,7 @@ void RTWindow::setProgress(double p) - - void RTWindow::setProgressStr(const Glib::ustring& str) - { -- if (!options.mainNBVertical) { -+ if (!App::get().options().mainNBVertical) { - prProgBar.set_text(str); - } - } -@@ -985,7 +992,7 @@ void RTWindow::MoveFileBrowserToEditor() - fpanel->ribbonPane->remove (*fCatalog); - fCatalog->disableInspector(); - epanel->catalogPane->add (*fCatalog); -- epanel->showTopPanel (options.editorFilmStripOpened); -+ epanel->showTopPanel (App::get().options().editorFilmStripOpened); - fCatalog->enableTabMode (true); - fCatalog->refreshHeight(); - fCatalog->tbLeftPanel_1_visible (false); -@@ -1003,7 +1010,7 @@ void RTWindow::updateExternalEditorWidget(int selectedIndex, const std::vectorupdateExternalEditorWidget(selectedIndex, editors); - } - -- if (options.multiDisplayMode > 0) { -+ if (App::get().options().multiDisplayMode > 0) { - EditWindow::getInstance(this) - ->updateExternalEditorWidget(selectedIndex, editors); - } -@@ -1080,7 +1087,7 @@ void RTWindow::updateToolPanelToolLocations( - panel.second->updateToolPanelToolLocations(favorites, cloneFavoriteTools); - } - -- if (options.multiDisplayMode > 0) { -+ if (App::get().options().multiDisplayMode > 0) { - EditWindow::getInstance(this) - ->updateToolPanelToolLocations(favorites, cloneFavoriteTools); - } -@@ -1098,6 +1105,7 @@ void RTWindow::setWindowSize () - { - onConfEventConn.block(true); // Avoid getting size and position while window is being moved, maximized, ... - -+ const auto& options = App::get().options(); - Gdk::Rectangle lMonitorRect; - const auto display = get_screen()->get_display(); - display->get_monitor (std::min (options.windowMonitor, display->get_n_monitors() - 1))->get_geometry(lMonitorRect); -@@ -1223,6 +1231,7 @@ void RTWindow::createSetmEditor() - setExpandAlignProperties (editorLabelGrid, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); - Gtk::Label* const el = Gtk::manage (new Gtk::Label ( Glib::ustring (" ") + M ("MAIN_FRAME_EDITOR") )); - -+ const auto& options = App::get().options(); - const auto pos = options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT; - - if (options.mainNBVertical) { -@@ -1241,5 +1250,6 @@ void RTWindow::createSetmEditor() - - bool RTWindow::isSingleTabMode() const - { -+ const auto& options = App::get().options(); - return !options.tabbedUI && ! (options.multiDisplayMode > 0); - } -diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc -index b1a217553..3bda96c81 100644 ---- a/rtgui/saveasdlg.cc -+++ b/rtgui/saveasdlg.cc -@@ -75,6 +75,7 @@ SaveAsDialog::SaveAsDialog (const Glib::ustring &initialDir, Gtk::Window* parent - filter_png->add_pattern("*.png"); - filter_png->add_pattern("*.PNG"); - -+ const auto& options = App::get().options(); - formatChanged (options.saveFormat.format); - - // Output Options -@@ -130,7 +131,7 @@ SaveAsDialog::SaveAsDialog (const Glib::ustring &initialDir, Gtk::Window* parent - Gtk::Box* vbox_bottomRight = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); - - // There is no queue in simple mode, so no need to choose -- if (!simpleEditor) { -+ if (!App::get().isSimpleEditor()) { - vbox_bottomRight->pack_start (*saveMethod[0], Gtk::PACK_SHRINK, 2); - vbox_bottomRight->pack_start (*saveMethod[1], Gtk::PACK_SHRINK, 2); - vbox_bottomRight->pack_start (*saveMethod[2], Gtk::PACK_SHRINK, 2); -@@ -190,7 +191,7 @@ bool SaveAsDialog::getAutoSuffix () - bool SaveAsDialog::getImmediately () - { - -- return simpleEditor ? true : saveMethod[0]->get_active (); -+ return App::get().isSimpleEditor() ? true : saveMethod[0]->get_active(); - } - - bool SaveAsDialog::getToHeadOfQueue () -@@ -207,7 +208,7 @@ bool SaveAsDialog::getToTailOfQueue () - - int SaveAsDialog::getSaveMethodNum () - { -- if (simpleEditor) { -+ if (App::get().isSimpleEditor()) { - return 0; - } - -diff --git a/rtgui/saveformatpanel.cc b/rtgui/saveformatpanel.cc -index d9b04e8fe..39d3977c0 100644 ---- a/rtgui/saveformatpanel.cc -+++ b/rtgui/saveformatpanel.cc -@@ -125,7 +125,7 @@ SaveFormatPanel::SaveFormatPanel () : listener (nullptr) - - SaveFormatPanel::~SaveFormatPanel () = default; - --void SaveFormatPanel::init (SaveFormat &sf) -+void SaveFormatPanel::init (const SaveFormat &sf) - { - FormatChangeListener* const tmp = listener; - listener = nullptr; -diff --git a/rtgui/saveformatpanel.h b/rtgui/saveformatpanel.h -index ba08c98f6..af6c4a72f 100644 ---- a/rtgui/saveformatpanel.h -+++ b/rtgui/saveformatpanel.h -@@ -58,7 +58,7 @@ public: - listener = l; - } - -- void init (SaveFormat& sf); -+ void init (const SaveFormat& sf); - SaveFormat getFormat (); - - void formatChanged (); -diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc -index 3104b641e..f7a1d2891 100644 ---- a/rtgui/sharpenedge.cc -+++ b/rtgui/sharpenedge.cc -@@ -36,6 +36,7 @@ SharpenEdge::SharpenEdge () : FoldableToolPanel(this, TOOL_NAME, M("TP_SHARPENED - passes = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_PASSES"), 1, 4, 1, 2)); - passes->setAdjusterListener (this); - -+ const auto& options = App::get().options(); - passes->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - amount = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_AMOUNT"), 0, 100, 1, 50)); -diff --git a/rtgui/soundman.cc b/rtgui/soundman.cc -index 5552bd12d..864e5e377 100644 ---- a/rtgui/soundman.cc -+++ b/rtgui/soundman.cc -@@ -49,7 +49,7 @@ void SoundManager::init() - // param is either file name or name of the system event on Windows (e.g. "SystemAsterisk" or "SystemDefault"). - void SoundManager::playSoundAsync(const Glib::ustring &sound) - { -- if (sound.empty() || !options.sndEnable) { -+ if (sound.empty() || !App::get().options().sndEnable) { - return; - } - -diff --git a/rtgui/splash.cc b/rtgui/splash.cc -index 0015c4864..2f075dbf0 100644 ---- a/rtgui/splash.cc -+++ b/rtgui/splash.cc -@@ -21,10 +21,7 @@ - #include - - #include "multilangmgr.h" -- --extern Glib::ustring creditsPath; --extern Glib::ustring licensePath; --extern Glib::ustring versionString; -+#include "rtengine/rtapp.h" - - SplashImage::SplashImage () : surface(new RTSurface("splash.svg")) - { -@@ -50,7 +47,7 @@ bool SplashImage::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) - context->set_font_description (fontd); - - int w, h; -- Glib::ustring versionStr(versionString); -+ Glib::ustring versionStr(App::VERSION); - - version = create_pango_layout (versionStr); - version->set_text(versionStr); -@@ -120,7 +117,7 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t - splashImage->show (); - - // Tab 2: the information about the current version -- std::string buildFileName = Glib::build_filename (creditsPath, "AboutThisBuild.txt"); -+ std::string buildFileName = Glib::build_filename (App::get().creditsPath(), "AboutThisBuild.txt"); - - if ( Glib::file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = g_fopen (buildFileName.c_str (), "rt"); -@@ -151,7 +148,7 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t - } - - // Tab 3: the credits -- std::string creditsFileName = Glib::build_filename (creditsPath, "AUTHORS.txt"); -+ std::string creditsFileName = Glib::build_filename (App::get().creditsPath(), "AUTHORS.txt"); - - if ( Glib::file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = g_fopen (creditsFileName.c_str (), "rt"); -@@ -183,7 +180,7 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t - } - - // Tab 4: the license -- std::string licenseFileName = Glib::build_filename (licensePath, "LICENSE"); -+ std::string licenseFileName = Glib::build_filename (App::get().licensePath(), "LICENSE"); - - if ( Glib::file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = g_fopen (licenseFileName.c_str (), "rt"); -@@ -216,7 +213,7 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t - } - - // Tab 5: the Release Notes -- std::string releaseNotesFileName = Glib::build_filename (creditsPath, "RELEASE_NOTES.txt"); -+ std::string releaseNotesFileName = Glib::build_filename (App::get().creditsPath(), "RELEASE_NOTES.txt"); - - if ( Glib::file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = g_fopen (releaseNotesFileName.c_str (), "rt"); -diff --git a/rtgui/thresholdadjuster.cc b/rtgui/thresholdadjuster.cc -index 5545a9f43..950e2462f 100644 ---- a/rtgui/thresholdadjuster.cc -+++ b/rtgui/thresholdadjuster.cc -@@ -80,7 +80,7 @@ void ThresholdAdjuster::initObject (Glib::ustring label, bool editedcb) - - addMode = false; - -- delay = options.adjusterMinDelay; -+ delay = App::get().options().adjusterMinDelay; - - set_name("ThresholdAdjuster"); - -diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc -index 15ad8831e..649476232 100644 ---- a/rtgui/thumbbrowserbase.cc -+++ b/rtgui/thumbbrowserbase.cc -@@ -30,7 +30,7 @@ - using namespace std; - - ThumbBrowserBase::ThumbBrowserBase () -- : location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), anchor(nullptr), previewHeight(options.thumbSize), numOfCols(1), lastRowHeight(0), arrangement(TB_Horizontal) -+ : location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), anchor(nullptr), previewHeight(App::get().options().thumbSize), numOfCols(1), lastRowHeight(0), arrangement(TB_Horizontal) - { - inW = -1; - inH = -1; -@@ -1101,10 +1101,11 @@ void ThumbBrowserBase::resort () - { - MYWRITERLOCK(l, entryRW); - -+ const auto& options = App::get().options(); - std::sort( - fd.begin(), - fd.end(), -- [](const ThumbBrowserEntryBase* a, const ThumbBrowserEntryBase* b) -+ [&](const ThumbBrowserEntryBase* a, const ThumbBrowserEntryBase* b) - { - bool lt = a->compare(*b, options.sortMethod); - return options.sortDescending ? !lt : lt; -@@ -1129,6 +1130,7 @@ void ThumbBrowserBase::zoomChanged (bool zoomIn) - int newHeight = 0; - int optThumbSize = getThumbnailHeight(); - -+ const auto& options = App::get().options(); - if (zoomIn) - for (size_t i = 0; i < options.thumbnailZoomRatios.size(); i++) { - newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight()); -@@ -1212,6 +1214,7 @@ void ThumbBrowserBase::enableTabMode(bool enable) - location = enable ? THLOC_EDITOR : THLOC_FILEBROWSER; - arrangement = enable ? ThumbBrowserBase::TB_Horizontal : ThumbBrowserBase::TB_Vertical; - -+ const auto& options = App::get().options(); - if ((!options.sameThumbSize && (options.thumbSizeTab != options.thumbSize)) || (options.showFileNames || options.filmStripShowFileNames)) { - - MYWRITERLOCK(l, entryRW); -@@ -1248,12 +1251,13 @@ void ThumbBrowserBase::insertEntry (ThumbBrowserEntryBase* entry) - { - MYWRITERLOCK(l, entryRW); - -+ const auto& options = App::get().options(); - fd.insert( - std::lower_bound( - fd.begin(), - fd.end(), - entry, -- [](const ThumbBrowserEntryBase* a, const ThumbBrowserEntryBase* b) -+ [&](const ThumbBrowserEntryBase* a, const ThumbBrowserEntryBase* b) - { - bool lt = a->compare(*b, options.sortMethod); - return options.sortDescending ? !lt : lt; -diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h -index 8c1ec49c8..9b3a927d9 100644 ---- a/rtgui/thumbbrowserbase.h -+++ b/rtgui/thumbbrowserbase.h -@@ -110,7 +110,7 @@ public: - protected: - virtual int getMaxThumbnailHeight() const - { -- return options.maxThumbnailHeight; // Differs between batch and file -+ return App::get().options().maxThumbnailHeight; // Differs between batch and file - } - virtual void saveThumbnailHeight (int height) = 0; - virtual int getThumbnailHeight () = 0; -diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc -index fd3f7d111..a47c0ca83 100644 ---- a/rtgui/thumbbrowserentrybase.cc -+++ b/rtgui/thumbbrowserentrybase.cc -@@ -263,6 +263,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () - int istartx = prex; - int istarty = prey; - -+ const auto& options = App::get().options(); - if ((parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && options.overlayedFileNames) - || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && options.filmStripOverlayedFileNames)) { - cc->begin_new_path (); -@@ -453,6 +454,8 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) - infow = 0; - - if (withFilename == WFNAME_FULL) { -+ const auto& options = App::get().options(); -+ - // datetime - fontd.set_weight (Pango::WEIGHT_NORMAL); - context->set_font_description (fontd); -@@ -503,6 +506,7 @@ void ThumbBrowserEntryBase::resize (int h) - buttonSet->getMinimalDimensions (bsw, bsh); - } - -+ const auto& options = App::get().options(); - if (parent->getLocation() == ThumbBrowserBase::THLOC_FILEBROWSER) { - if (options.showFileNames) { - withFilename = WFNAME_FULL; -@@ -738,6 +742,7 @@ std::tuple ThumbBrowserEntryBase::getToolTip (int x, int y) - if (inside(x, y) && tooltip.empty()) { - tooltip = dispname; - -+ const auto& options = App::get().options(); - if (withFilename < WFNAME_FULL) { - if (options.fbShowDateTime && !datetimeline.empty()) { - tooltip += Glib::ustring("\n") + datetimeline; -diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc -index e7f117101..0f63dae5b 100644 ---- a/rtgui/thumbnail.cc -+++ b/rtgui/thumbnail.cc -@@ -74,6 +74,7 @@ bool CPBDump( - return false; - } - -+ const auto& options = App::get().options(); - try { - kf->set_string ("RT General", "CachePath", options.cacheBaseDir); - kf->set_string ("RT General", "AppVersion", RTVERSION); -@@ -361,6 +362,7 @@ void Thumbnail::_generateThumbnailImage() - tpp = nullptr; - delete[] lastImg; - lastImg = nullptr; -+ const auto& options = App::get().options(); - tw = options.maxThumbnailWidth; - th = options.maxThumbnailHeight; - imgRatio = -1.; -@@ -477,6 +479,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu - // try to load the last saved parameters from the cache or from the paramfile file - ProcParams* ldprof = nullptr; - -+ const auto& options = App::get().options(); - Glib::ustring defProf = getType() == FT_Raw ? options.defProfRaw : options.defProfImg; - - const CacheImageData* cfs = getCacheImageData(); -@@ -486,8 +489,8 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu - - const Glib::ustring outFName = - (options.paramsLoadLocation == PLL_Input && options.saveParamsFile) ? -- fname + paramFileExtension : -- getCacheFileName("profiles", paramFileExtension); -+ fname + App::PARAM_FILE_EXTENSION : -+ getCacheFileName("profiles", App::PARAM_FILE_EXTENSION); - - if (!run_cpb) { - if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { -@@ -519,7 +522,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu - Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) ); - - CPBDump(tmpFileName, fname, outFName, -- defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, flaggingMode); -+ defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + App::PARAM_FILE_EXTENSION), cfs, flaggingMode); - - // For the filename etc. do NOT use streams, since they are not UTF8 safe - Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\""); -@@ -567,22 +570,22 @@ void Thumbnail::loadProcParams() - pparamsValid = false; - pparams->setDefaults(); - -- if (options.paramsLoadLocation == PLL_Input) { -+ if (App::get().options().paramsLoadLocation == PLL_Input) { - // try to load it from params file next to the image file -- const int ppres = pparams->load(fname + paramFileExtension); -+ const int ppres = pparams->load(fname + App::PARAM_FILE_EXTENSION); - pparamsValid = !ppres && pparams->ppVersion >= 220; - - // if no success, try to load the cached version of the procparams - if (!pparamsValid) { -- pparamsValid = !pparams->load(getCacheFileName("profiles", paramFileExtension)); -+ pparamsValid = !pparams->load(getCacheFileName("profiles", App::PARAM_FILE_EXTENSION)); - } - } else { - // try to load it from cache -- pparamsValid = !pparams->load(getCacheFileName("profiles", paramFileExtension)); -+ pparamsValid = !pparams->load(getCacheFileName("profiles", App::PARAM_FILE_EXTENSION)); - - // if no success, try to load it from params file next to the image file - if (!pparamsValid) { -- const int ppres = pparams->load(fname + paramFileExtension); -+ const int ppres = pparams->load(fname + App::PARAM_FILE_EXTENSION); - pparamsValid = !ppres && pparams->ppVersion >= 220; - } - } -@@ -620,17 +623,17 @@ void Thumbnail::clearProcParams (int whoClearedIt) - updateCache(); - } else { - // remove param file from cache -- Glib::ustring fname_ = getCacheFileName ("profiles", paramFileExtension); -+ Glib::ustring fname_ = getCacheFileName ("profiles", App::PARAM_FILE_EXTENSION); - g_remove (fname_.c_str ()); - - // remove param file located next to the file -- fname_ = fname + paramFileExtension; -+ fname_ = fname + App::PARAM_FILE_EXTENSION; - g_remove (fname_.c_str ()); - -- fname_ = removeExtension(fname) + paramFileExtension; -+ fname_ = removeExtension(fname) + App::PARAM_FILE_EXTENSION; - g_remove (fname_.c_str ()); - -- if (cfs.format == FT_Raw && options.internalThumbIfUntouched && cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL) { -+ if (cfs.format == FT_Raw && App::get().options().internalThumbIfUntouched && cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL) { - // regenerate thumbnail, ie load the quick thumb again. For the rare formats not supporting quick thumbs this will - // be a bit slow as a new full thumbnail will be generated unnecessarily, but currently there is no way to pre-check - // if the format supports quick thumbs. -@@ -748,8 +751,8 @@ void Thumbnail::imageDeveloped () - cfs.recentlySaved = true; - cfs.save (getCacheFileName ("data", ".txt")); - -- if (options.saveParamsCache) { -- pparams->save (getCacheFileName ("profiles", paramFileExtension)); -+ if (App::get().options().saveParamsCache) { -+ pparams->save (getCacheFileName ("profiles", App::PARAM_FILE_EXTENSION)); - } - } - -@@ -839,6 +842,7 @@ void Thumbnail::getThumbnailSize(int &w, int &h, const rtengine::procparams::Pro - w = tw_ * h / th_; - } - -+ const auto& options = App::get().options(); - if (w > options.maxThumbnailWidth) { - const float s = static_cast(options.maxThumbnailWidth) / w; - w = options.maxThumbnailWidth; -@@ -931,6 +935,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro - - void Thumbnail::generateExifDateTimeStrings () - { -+ const auto& options = App::get().options(); - if (cfs.timeValid) { - std::string dateFormat = options.dateFormat; - std::ostringstream ostr; -@@ -1100,7 +1105,7 @@ void Thumbnail::_loadThumbnail(bool firstTrial) - { - - tw = -1; -- th = options.maxThumbnailHeight; -+ th = App::get().options().maxThumbnailHeight; - delete tpp; - tpp = new rtengine::Thumbnail (); - tpp->isRaw = (cfs.format == (int) FT_Raw); -@@ -1195,9 +1200,10 @@ void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData) - updateProcParamsProperties(); - - if (updatePParams && pparamsValid) { -+ const auto& options = App::get().options(); - pparams->save ( -- options.saveParamsFile ? fname + paramFileExtension : "", -- options.saveParamsCache ? getCacheFileName ("profiles", paramFileExtension) : "", -+ options.saveParamsFile ? fname + App::PARAM_FILE_EXTENSION : "", -+ options.saveParamsCache ? getCacheFileName ("profiles", App::PARAM_FILE_EXTENSION) : "", - true - ); - } -@@ -1292,6 +1298,7 @@ bool Thumbnail::openDefaultViewer(int destination) - #ifdef _WIN32 - Glib::ustring openFName; - -+ const auto& options = App::get().options(); - if (destination == 1) { - openFName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - -@@ -1382,6 +1389,8 @@ void Thumbnail::loadProperties() - // get initial rank from cache or image metadata - getRankFromMetadata(cfs, fname, properties.rank.value); - -+ const auto& options = App::get().options(); -+ - // update rank and color from procparams or xmp sidecar - // load trash from procparams - if (pparamsValid) { -@@ -1423,6 +1432,8 @@ void Thumbnail::updateProcParamsProperties(bool forceUpdate) - return rtengine::Exiv2Metadata::getXmpSidecar(fname); - }); - -+ const auto& options = App::get().options(); -+ - // save procparams rank and color also when options.thumbnailRankColorMode == Options::ThumbnailPropertyMode::XMP - // so they'll be kept in sync - // Rank can be -1 to prioritize the rank in the metadata. If the metadata -@@ -1465,7 +1476,7 @@ void Thumbnail::saveXMPSidecarProperties() - return; - } - -- if (options.thumbnailRankColorMode != Options::ThumbnailPropertyMode::XMP) { -+ if (App::get().options().thumbnailRankColorMode != Options::ThumbnailPropertyMode::XMP) { - return; - } - -@@ -1490,6 +1501,7 @@ void Thumbnail::saveXMPSidecarProperties() - - void Thumbnail::saveMetadata() - { -+ const auto& options = App::get().options(); - if (options.rtSettings.metadata_xmp_sync != rtengine::Settings::MetadataXmpSync::READ_WRITE) { - return; - } -diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc -index 9fb6e17e1..c88d111cb 100644 ---- a/rtgui/tonecurve.cc -+++ b/rtgui/tonecurve.cc -@@ -178,6 +178,7 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL - toneCurveMode->set_active(0); - toneCurveMode->set_tooltip_text(M("TP_EXPOSURE_TCMODE_LABEL1")); - -+ auto& options = App::get().mut_options(); - curveEditorG = new CurveEditorGroup(options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR1")); - curveEditorG->setCurveListener(this); - -diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc -index dd9c00af5..32c04f417 100644 ---- a/rtgui/toolpanelcoord.cc -+++ b/rtgui/toolpanelcoord.cc -@@ -470,6 +470,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit - vbPanelEnd[i]->pack_start(*imgPanelEnd[i], Gtk::PACK_SHRINK); - vbPanelEnd[i]->show_all(); - } -+ const auto& options = App::get().options(); - updateVScrollbars(options.hideTPVScrollbar); - - Gtk::Box *favoritePanelContainer = -@@ -763,6 +764,7 @@ bool ToolPanelCoordinator::isFavoritable(Tool tool) - - void ToolPanelCoordinator::notebookPageChanged(Gtk::Widget* page, guint page_num) - { -+ const auto& options = App::get().options(); - updatePanelTools(page, options.favorites, options.cloneFavoriteTools); - - // Locallab spot curves are set visible if at least one photo has been loaded (to avoid -@@ -1425,6 +1427,7 @@ void ToolPanelCoordinator::closeImage() - - void ToolPanelCoordinator::closeAllTools() - { -+ const auto& options = App::get().options(); - for (size_t i = 0; i < options.tpOpen.size(); ++i) { - if (i < expList.size()) { - expList[i]->set_expanded(false); -@@ -1434,6 +1437,7 @@ void ToolPanelCoordinator::closeAllTools() - - void ToolPanelCoordinator::openAllTools() - { -+ const auto& options = App::get().options(); - for (size_t i = 0; i < options.tpOpen.size(); ++i) { - if (i < expList.size()) { - expList[i]->set_expanded(true); -@@ -1443,6 +1447,7 @@ void ToolPanelCoordinator::openAllTools() - - void ToolPanelCoordinator::updateToolState() - { -+ const auto& options = App::get().options(); - if (options.tpOpen.empty()) { - for (auto expander : expList) { - expander->set_expanded(false); -@@ -1485,6 +1490,7 @@ void ToolPanelCoordinator::writeOptions() - - crop->writeOptions(); - -+ auto& options = App::get().mut_options(); - if (options.autoSaveTpOpen) { - writeToolExpandedStatus(options.tpOpen); - } -@@ -1956,6 +1962,7 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) - break; - } - -+ const auto& options = App::get().options(); - updateToolLocations(options.favorites, options.cloneFavoriteTools); - - notebookconn.block(false); -diff --git a/rtgui/vibrance.cc b/rtgui/vibrance.cc -index c928519c5..b554d2a34 100644 ---- a/rtgui/vibrance.cc -+++ b/rtgui/vibrance.cc -@@ -67,6 +67,7 @@ Vibrance::Vibrance () : FoldableToolPanel(this, TOOL_NAME, M("TP_VIBRANCE_LABEL" - pastSatTog->set_active (true); - pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); - -+ auto& options = App::get().mut_options(); - curveEditorGG = new CurveEditorGroup (options.lastVibranceCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL")); - curveEditorGG->setCurveListener (this); - -diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc -index f1be5d17d..50217cd4a 100644 ---- a/rtgui/wavelet.cc -+++ b/rtgui/wavelet.cc -@@ -65,22 +65,22 @@ std::vector makeWholeHueRange() - - Wavelet::Wavelet() : - FoldableToolPanel(this, TOOL_NAME, M("TP_WAVELET_LABEL"), true, true), -- curveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))), -- //curveEditorC(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CONTRASTEDIT"))), -- CCWcurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))), -- curveEditorbl(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_BLCURVE"))), -- curveEditorRES(new CurveEditorGroup(options.lastWaveletCurvesDir)), -- curveEditorGAM(new CurveEditorGroup(options.lastWaveletCurvesDir)), -+ curveEditorG(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT"))), -+ //curveEditorC(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_CONTRASTEDIT"))), -+ CCWcurveEditorG(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_CCURVE"))), -+ curveEditorbl(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_BLCURVE"))), -+ curveEditorRES(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir)), -+ curveEditorGAM(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir)), - separatorNeutral(Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL))), - separatoredge(Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL))), -- opaCurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_COLORT"))), -- opacityCurveEditorG(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITY"))), -- CurveEditorwavnoise(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISE"))), -- CurveEditorwavnoiseh(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEH"))), -- CurveEditorwavguid(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEGUID"))), -- CurveEditorwavhue(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_DENOISEHUE"))), -- opacityCurveEditorW(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYW"))), -- opacityCurveEditorWL(new CurveEditorGroup(options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYWL"))), -+ opaCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_COLORT"))), -+ opacityCurveEditorG(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_OPACITY"))), -+ CurveEditorwavnoise(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_DENOISE"))), -+ CurveEditorwavnoiseh(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_DENOISEH"))), -+ CurveEditorwavguid(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_DENOISEGUID"))), -+ CurveEditorwavhue(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_DENOISEHUE"))), -+ opacityCurveEditorW(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_OPACITYW"))), -+ opacityCurveEditorWL(new CurveEditorGroup(App::get().mut_options().lastWaveletCurvesDir, M("TP_WAVELET_OPACITYWL"))), - median(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_MEDI")))), - medianlev(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_MEDILEV")))), - linkedg(Gtk::manage(new Gtk::CheckButton(M("TP_WAVELET_LINKEDG")))), -diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc -index c0a65f7f4..c8428f257 100644 ---- a/rtgui/whitebalance.cc -+++ b/rtgui/whitebalance.cc -@@ -281,6 +281,7 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, TOOL_NAME, M("TP_WBALANC - setExpandAlignProperties(spotsize, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - spotsize->append ("2"); - -+ const auto& options = App::get().options(); - if (options.whiteBalanceSpotSize == 2) { - spotsize->set_active(0); - } -@@ -745,7 +746,7 @@ void WhiteBalance::spotPressed () - - void WhiteBalance::spotSizeChanged () - { -- options.whiteBalanceSpotSize = getSize(); -+ App::get().mut_options().whiteBalanceSpotSize = getSize(); - - if (wblistener) { - wblistener->spotWBRequested (getSize()); -@@ -785,7 +786,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) - - - -- if(options.rtSettings.itcwb_enable) { -+ if(App::get().options().rtSettings.itcwb_enable) { - itcwb_green->show(); - itcwb_alg->show(); - itcwb_prim->show(); -diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc -index de2e14725..2b2beac24 100644 ---- a/rtgui/xtransprocess.cc -+++ b/rtgui/xtransprocess.cc -@@ -29,7 +29,7 @@ using namespace rtengine::procparams; - - const Glib::ustring XTransProcess::TOOL_NAME = "xtransprocess"; - --XTransProcess::XTransProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar) -+XTransProcess::XTransProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), App::get().options().prevdemo != PD_Sidecar) - { - auto m = ProcEventMapper::getInstance(); - EvDemosaicBorder = m->newEvent(DEMOSAIC, "HISTORY_MSG_RAW_BORDER"); -@@ -74,6 +74,7 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_L - hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); - -+ const auto& options = App::get().options(); - dualDemosaicOptions = Gtk::manage (new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); - - dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20)); -diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc -index e4c1c55d0..496d0d308 100644 ---- a/rtgui/xtransrawexposure.cc -+++ b/rtgui/xtransrawexposure.cc -@@ -38,6 +38,7 @@ XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M(" - PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"), -2048, 2048, 1.0, 0)); //black level - PexBlackRed->setAdjusterListener (this); - -+ const auto& options = App::get().options(); - PexBlackRed->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); - - PexBlackRed->show(); --- -2.50.1 - diff --git a/0001-Fix-typos.patch b/0001-Fix-typos.patch deleted file mode 100644 index bd087fa..0000000 --- a/0001-Fix-typos.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d12ca94d42c1370d70fb14cc185d46aaca9c05ac Mon Sep 17 00:00:00 2001 -From: Daniel Gao -Date: Sun, 24 Aug 2025 11:37:06 -0400 -Subject: [PATCH] Fix typos - ---- - rtgui/filepanel.cc | 2 +- - rtgui/main.cc | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc -index f069f099e..28bee9839 100644 ---- a/rtgui/filepanel.cc -+++ b/rtgui/filepanel.cc -@@ -208,7 +208,7 @@ void FilePanel::init () - dirBrowser->fillDirTree (); - placesBrowser->refreshPlacesList (); - -- if (!App::get().argv0().empty() && Glib::file_test (App::get().argv1(), Glib::FILE_TEST_EXISTS)) { -+ if (!App::get().argv1().empty() && Glib::file_test (App::get().argv1(), Glib::FILE_TEST_EXISTS)) { - Glib::ustring d(App::get().argv1()); - if (!Glib::file_test(d, Glib::FILE_TEST_IS_DIR)) { - d = Glib::path_get_dirname(d); -diff --git a/rtgui/main.cc b/rtgui/main.cc -index ded7076be..180e43f5d 100644 ---- a/rtgui/main.cc -+++ b/rtgui/main.cc -@@ -139,7 +139,7 @@ int processLineParams ( int argc, char **argv ) - if (currParam == "-gimp") { - app.setIsGimpPlugin(true); - app.setIsSimpleEditor(true); -- app.setIsRemote(true); -+ app.setIsRemote(false); - break; - } - --- -2.51.1 - diff --git a/RT_5.8_fix_canon_sraw.patch b/RT_5.8_fix_canon_sraw.patch new file mode 100644 index 0000000..285bfef --- /dev/null +++ b/RT_5.8_fix_canon_sraw.patch @@ -0,0 +1,22 @@ +From 4221fdf31e43658cef98ad660ad398b8ae81b8d7 Mon Sep 17 00:00:00 2001 +From: Ingo Weyrich +Date: Fri, 7 Feb 2020 13:52:25 +0100 +Subject: [PATCH] fix regression in Canon sRAW/mRAW black level computation, + taken from ART, fixes #5638 + +--- + rtengine/dcraw.cc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc +index 812f122b3..0284b3f1d 100644 +--- a/rtengine/dcraw.cc ++++ b/rtengine/dcraw.cc +@@ -9868,6 +9868,7 @@ void CLASS identify() + filters = 0; + tiff_samples = colors = 3; + load_raw = &CLASS canon_sraw_load_raw; ++ FORC4 cblack[c] = 0; // ALB + } else if (!strcmp(model,"PowerShot 600")) { + height = 613; + width = 854; diff --git a/RT_5.8_fix_crop.patch b/RT_5.8_fix_crop.patch new file mode 100644 index 0000000..24cbfdc --- /dev/null +++ b/RT_5.8_fix_crop.patch @@ -0,0 +1,221 @@ +From 15db8cdb57161d57af8307bf85aeda02ea69ddde Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fl=C3=B6ssie?= +Date: Sun, 5 Apr 2020 11:26:47 +0200 +Subject: [PATCH] Guard accesses to `Crop::crop_ratios` (#5701) + +--- + rtgui/crop.cc | 125 +++++++++++++++++++++++++++++++++++--------------- + rtgui/crop.h | 11 ++--- + 2 files changed, 92 insertions(+), 44 deletions(-) + +diff --git a/rtgui/crop.cc b/rtgui/crop.cc +index d9d496523..f092f07a5 100644 +--- a/rtgui/crop.cc ++++ b/rtgui/crop.cc +@@ -16,6 +16,8 @@ + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ ++#include ++ + #include "crop.h" + + #include "options.h" +@@ -46,39 +48,82 @@ inline void get_custom_ratio(int w, int h, double &rw, double &rh) + + } // namespace + ++class Crop::CropRatios final ++{ ++public: ++ CropRatios() : ++ ratios{ ++ {M("GENERAL_ASIMAGE"), 0.0}, ++ {M("GENERAL_CURRENT"), -1.0}, ++ {"3:2", 3.0 / 2.0}, // L1.5, P0.666... ++ {"4:3", 4.0 / 3.0}, // L1.333..., P0.75 ++ {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625 ++ {"16:10", 16.0 / 10.0}, // L1.6, P0.625 ++ {"1:1", 1.0 / 1.0}, // L1, P1 ++ {"2:1", 2.0 / 1.0}, // L2, P0.5 ++ {"3:1", 3.0 / 1.0}, // L3, P0.333... ++ {"4:1", 4.0 / 1.0}, // L4, P0.25 ++ {"5:1", 5.0 / 1.0}, // L5, P0.2 ++ {"6:1", 6.0 / 1.0}, // L6, P0.1666... ++ {"7:1", 7.0 / 1.0}, // L7, P0.142... ++ {"4:5", 4.0 / 5.0}, // L1.25, P0.8 ++ {"5:7", 5.0 / 7.0}, // L1.4, P0.714... ++ {"6:7", 6.0 / 7.0}, // L1.166..., P0.857... ++ {"6:17", 6.0 / 17.0}, // L2.833..., P0.352... ++ {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369... ++ {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707... ++ {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7 ++ {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772... ++ {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791... ++ {"10:12", 10.0 / 12.0}, // L1.2, P0.833... ++ {"11:14", 11.0 / 14.0}, // L1.272..., P0.785... ++ {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647... ++ {"13:19", 13.0 / 19.0}, // L1.461..., P0.684... ++ {"17:22", 17.0 / 22.0}, // L1.294..., P0.772... ++ {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777... ++ {"64:27", 64.0 / 27.0}, // L2.370..., P0.421... ++ } ++ { ++ } ++ ++ std::vector getLabels() const ++ { ++ std::vector res; ++ ++ res.reserve(ratios.size()); ++ ++ for (const auto& ratio : ratios) { ++ res.push_back(ratio.label); ++ } ++ ++ return res; ++ } ++ ++ double getValue(std::size_t index) const ++ { ++ return ++ index < ratios.size() ++ ? ratios[index].value ++ : ratios[0].value; ++ } ++ ++ void updateCurrentRatio(double value) ++ { ++ ratios[1].value = value; ++ } ++ ++private: ++ struct CropRatio { ++ Glib::ustring label; ++ double value; ++ }; ++ ++ std::vector ratios; ++}; ++ + Crop::Crop(): + FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true), +- crop_ratios{ +- {M("GENERAL_ASIMAGE"), 0.0}, +- {M("GENERAL_CURRENT"), -1.0}, +- {"3:2", 3.0 / 2.0}, // L1.5, P0.666... +- {"4:3", 4.0 / 3.0}, // L1.333..., P0.75 +- {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625 +- {"16:10", 16.0 / 10.0}, // L1.6, P0.625 +- {"1:1", 1.0 / 1.0}, // L1, P1 +- {"2:1", 2.0 / 1.0}, // L2, P0.5 +- {"3:1", 3.0 / 1.0}, // L3, P0.333... +- {"4:1", 4.0 / 1.0}, // L4, P0.25 +- {"5:1", 5.0 / 1.0}, // L5, P0.2 +- {"6:1", 6.0 / 1.0}, // L6, P0.1666... +- {"7:1", 7.0 / 1.0}, // L7, P0.142... +- {"4:5", 4.0 / 5.0}, // L1.25, P0.8 +- {"5:7", 5.0 / 7.0}, // L1.4, P0.714... +- {"6:7", 6.0 / 7.0}, // L1.166..., P0.857... +- {"6:17", 6.0 / 17.0}, // L2.833..., P0.352... +- {"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369... +- {"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707... +- {"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7 +- {"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772... +- {"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791... +- {"10:12", 10.0 / 12.0}, // L1.2, P0.833... +- {"11:14", 11.0 / 14.0}, // L1.272..., P0.785... +- {"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647... +- {"13:19", 13.0 / 19.0}, // L1.461..., P0.684... +- {"17:22", 17.0 / 22.0}, // L1.294..., P0.772... +- {"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777... +- {"64:27", 64.0 / 27.0}, // L2.370..., P0.421... +- }, ++ crop_ratios(new CropRatios), + opt(0), + wDirty(true), + hDirty(true), +@@ -229,8 +274,8 @@ Crop::Crop(): + // ppigrid END + + // Populate the combobox +- for (const auto& crop_ratio : crop_ratios) { +- ratio->append (crop_ratio.label); ++ for (const auto& label : crop_ratios->getLabels()) { ++ ratio->append (label); + } + + ratio->set_active (0); +@@ -354,7 +399,10 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) + setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h); + } + +- const bool flip_orientation = pp->crop.fixratio && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0; ++ const bool flip_orientation = ++ pp->crop.fixratio ++ && crop_ratios->getValue(ratio->get_active_row_number()) > 0 ++ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0; + + if (pp->crop.orientation == "Landscape") { + orientation->set_active (flip_orientation ? 1 : 0); +@@ -469,7 +517,10 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited) + } + + // for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first. +- const bool flip_orientation = fixr->get_active() && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0; ++ const bool flip_orientation = ++ fixr->get_active() ++ && crop_ratios->getValue(ratio->get_active_row_number()) > 0 ++ && crop_ratios->getValue(ratio->get_active_row_number()) < 1.0; + + if (orientation->get_active_row_number() == 0) { + pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape"; +@@ -1501,7 +1552,7 @@ double Crop::getRatio () const + return r; + } + +- r = crop_ratios[ratio->get_active_row_number()].value; ++ r = crop_ratios->getValue(ratio->get_active_row_number()); + if (!r) { + r = maxh <= maxw ? float(maxh)/float(maxw) : float(maxw)/float(maxh); + } +@@ -1539,5 +1590,5 @@ void Crop::updateCurrentRatio() + double rw, rh; + get_custom_ratio(w->get_value(), h->get_value(), rw, rh); + customRatioLabel->set_text(Glib::ustring::compose("%1:%2", rw, rh)); +- crop_ratios[1].value = double(w->get_value())/double(h->get_value()); ++ crop_ratios->updateCurrentRatio(static_cast(w->get_value()) / static_cast(h->get_value())); + } +diff --git a/rtgui/crop.h b/rtgui/crop.h +index b9221a803..c6636b917 100644 +--- a/rtgui/crop.h ++++ b/rtgui/crop.h +@@ -18,7 +18,7 @@ + */ + #pragma once + +-#include ++#include + + #include + +@@ -91,16 +91,13 @@ class Crop final : + void rotateCrop (int deg, bool hflip, bool vflip); + + private: +- struct CropRatio { +- Glib::ustring label; +- double value; +- }; +- +- std::vector crop_ratios; ++ class CropRatios; + + void adjustCropToRatio(); + void updateCurrentRatio(); + ++ const std::unique_ptr crop_ratios; ++ + Gtk::CheckButton* fixr; + MyComboBoxText* ratio; + MyComboBoxText* orientation; diff --git a/RT_5.8_fix_nikon_z_exif.patch b/RT_5.8_fix_nikon_z_exif.patch new file mode 100644 index 0000000..524868c --- /dev/null +++ b/RT_5.8_fix_nikon_z_exif.patch @@ -0,0 +1,63 @@ +From 84b59f187aa8418e0b5f0986caa6a5a7e5f08136 Mon Sep 17 00:00:00 2001 +From: Anders Bennehag +Date: Sun, 21 Jun 2020 14:08:45 -0400 +Subject: [PATCH] createJPEGMarker(): Removes MakerNotes.ShotInfo from jpeg + export + +as it is 52Kb large on Nikon Z-series cameras, which results in +jpeg exif tags being larger than allowed 65Kb limit. + +Fixes https://github.com/Beep6581/RawTherapee/issues/5698 +--- + rtexif/rtexif.cc | 38 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 37 insertions(+), 1 deletion(-) + +diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc +index c0038c067..f32a9feb1 100644 +--- a/rtexif/rtexif.cc ++++ b/rtexif/rtexif.cc +@@ -3248,7 +3248,43 @@ int ExifManager::createJPEGMarker (const TagDirectory* root, const rtengine::pro + TagDirectory* cl; + + if (root) { +- cl = (const_cast (root))->clone (nullptr); ++ cl = root->clone(nullptr); ++ ++ // Drop unwanted tags before exporting ++ // For example, Nikon Z-series has a 52Kb MakerNotes->ShotInfo tag ++ // which does not fit into the 65Kb limit on JPEG exif tags ++ const Tag* const make_tag = cl->getTag(271); ++ if (make_tag && !std::strncmp((const char*)make_tag->getValue(), "NIKON CORPORATION", 17)) { ++ [cl]() ++ { ++ Tag* const exif_tag = cl->getTag(34665); ++ if (!exif_tag) { ++ return; ++ } ++ ++ TagDirectory* const exif_dir = exif_tag->getDirectory(); ++ if (!exif_dir) { ++ return; ++ } ++ ++ Tag* const make_notes_tag = exif_dir->getTag(37500); ++ if (!make_notes_tag) { ++ return; ++ } ++ ++ TagDirectory* const maker_notes_dir = make_notes_tag->getDirectory(); ++ if (!maker_notes_dir) { ++ return; ++ } ++ ++ Tag* const shot_info_tag = maker_notes_dir->getTag(145); ++ if (!shot_info_tag) { ++ return; ++ } ++ ++ shot_info_tag->setKeep(false); ++ }(); ++ } + } else { + cl = new TagDirectory (nullptr, ifdAttribs, INTEL); + } diff --git a/RT_5.8_glibc234.patch b/RT_5.8_glibc234.patch new file mode 100644 index 0000000..791183e --- /dev/null +++ b/RT_5.8_glibc234.patch @@ -0,0 +1,683 @@ +diff -udHrN -- a/RT_5.8_glibc234.patch b/RT_5.8_glibc234.patch +--- a/RT_5.8_glibc234.patch 1970-01-01 01:00:00.000000000 +0100 ++++ b/RT_5.8_glibc234.patch 2021-08-04 18:50:22.142646367 +0200 +@@ -0,0 +1,334 @@ ++diff --git a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc ++index ddd4b6172..1132b4e01 100644 ++--- a/rtengine/canon_cr3_decoder.cc +++++ b/rtengine/canon_cr3_decoder.cc ++@@ -670,7 +670,7 @@ std::uint32_t _byteswap_ulong(std::uint32_t x) ++ #endif ++ ++ struct LibRaw_abstract_datastream { ++- IMFILE* ifp; +++ rtengine::IMFILE* ifp; ++ ++ void lock() ++ { ++diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc ++index ef0b4e8dc..13a6b054a 100644 ++--- a/rtengine/dcraw.cc +++++ b/rtengine/dcraw.cc ++@@ -1963,7 +1963,7 @@ void CLASS phase_one_load_raw_c() ++ #endif ++ { ++ int len[2], pred[2]; ++- IMFILE ifpthr = *ifp; +++ rtengine::IMFILE ifpthr = *ifp; ++ ifpthr.plistener = nullptr; ++ ++ #ifdef _OPENMP ++@@ -3317,7 +3317,7 @@ void CLASS sony_arw2_load_raw() ++ { ++ uchar *data = new (std::nothrow) uchar[raw_width + 1]; ++ merror(data, "sony_arw2_load_raw()"); ++- IMFILE ifpthr = *ifp; +++ rtengine::IMFILE ifpthr = *ifp; ++ int pos = ifpthr.pos; ++ ushort pix[16]; ++ ++@@ -6331,7 +6331,7 @@ int CLASS parse_tiff_ifd (int base) ++ unsigned sony_curve[] = { 0,0,0,0,0,4095 }; ++ unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; ++ struct jhead jh; ++-/*RT*/ IMFILE *sfp; +++/*RT*/ rtengine::IMFILE *sfp; ++ /*RT*/ int pana_raw = 0; ++ ++ if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) ++@@ -6895,7 +6895,7 @@ it under the terms of the one of two licenses as you choose: ++ fread (buf, sony_length, 1, ifp); ++ sony_decrypt (buf, sony_length/4, 1, sony_key); ++ sfp = ifp; ++-/*RT*/ ifp = fopen (buf, sony_length); +++/*RT*/ ifp = rtengine::fopen (buf, sony_length); ++ // if ((ifp = tmpfile())) { ++ // fwrite (buf, sony_length, 1, ifp); ++ // fseek (ifp, 0, SEEK_SET); ++@@ -7203,7 +7203,7 @@ void CLASS parse_external_jpeg() ++ { ++ const char *file, *ext; ++ char *jname, *jfile, *jext; ++-/*RT*/ IMFILE *save=ifp; +++/*RT*/ rtengine::IMFILE *save=ifp; ++ ++ ext = strrchr (ifname, '.'); ++ file = strrchr (ifname, '/'); ++@@ -7231,7 +7231,7 @@ void CLASS parse_external_jpeg() ++ *jext = '0'; ++ } ++ if (strcmp (jname, ifname)) { ++-/*RT*/ if ((ifp = fopen (jname))) { +++/*RT*/ if ((ifp = rtengine::fopen (jname))) { ++ // if ((ifp = fopen (jname, "rb"))) { ++ if (verbose) ++ fprintf (stderr,_("Reading metadata from %s ...\n"), jname); ++diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h ++index 10c7b9ba6..bc009e67c 100644 ++--- a/rtengine/dcraw.h +++++ b/rtengine/dcraw.h ++@@ -73,7 +73,7 @@ public: ++ ++ protected: ++ int exif_base, ciff_base, ciff_len; ++- IMFILE *ifp; +++ rtengine::IMFILE *ifp; ++ FILE *ofp; ++ short order; ++ const char *ifname; ++@@ -125,7 +125,7 @@ protected: ++ int cur_buf_size; // buffer size ++ uchar *cur_buf; // currently read block ++ int fillbytes; // Counter to add extra byte for block size N*16 ++- IMFILE *input; +++ rtengine::IMFILE *input; ++ struct int_pair grad_even[3][41]; // tables of gradients ++ struct int_pair grad_odd[3][41]; ++ ushort *linealloc; ++@@ -278,7 +278,7 @@ void parse_redcine(); ++ class getbithuff_t ++ { ++ public: ++- getbithuff_t(DCraw *p,IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){} +++ getbithuff_t(DCraw *p,rtengine::IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){} ++ unsigned operator()(int nbits, ushort *huff); ++ ++ private: ++@@ -288,7 +288,7 @@ private: ++ DCraw *parent; ++ unsigned bitbuf; ++ int vbits, reset; ++- IMFILE *&ifp; +++ rtengine::IMFILE *&ifp; ++ unsigned &zero_after_ff; ++ }; ++ getbithuff_t getbithuff; ++@@ -296,7 +296,7 @@ getbithuff_t getbithuff; ++ class nikbithuff_t ++ { ++ public: ++- explicit nikbithuff_t(IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){} +++ explicit nikbithuff_t(rtengine::IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){} ++ void operator()() {bitbuf = vbits = 0;}; ++ unsigned operator()(int nbits, ushort *huff); ++ unsigned errorCount() { return errors; } ++@@ -309,7 +309,7 @@ private: ++ } ++ unsigned bitbuf, errors; ++ int vbits; ++- IMFILE *&ifp; +++ rtengine::IMFILE *&ifp; ++ }; ++ nikbithuff_t nikbithuff; ++ ++@@ -377,7 +377,7 @@ void parse_qt (int end); ++ // ph1_bithuff(int nbits, ushort *huff); ++ class ph1_bithuff_t { ++ public: ++- ph1_bithuff_t(DCraw *p, IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){} +++ ph1_bithuff_t(DCraw *p, rtengine::IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){} ++ unsigned operator()(int nbits, ushort *huff); ++ unsigned operator()(int nbits); ++ unsigned operator()(); ++@@ -411,7 +411,7 @@ private: ++ } ++ ++ short ℴ ++- IMFILE* const ifp; +++ rtengine::IMFILE* const ifp; ++ UINT64 bitbuf; ++ int vbits; ++ }; ++@@ -429,11 +429,11 @@ void nokia_load_raw(); ++ ++ class pana_bits_t{ ++ public: ++- pana_bits_t(IMFILE *i, unsigned &u, unsigned enc): +++ pana_bits_t(rtengine::IMFILE *i, unsigned &u, unsigned enc): ++ ifp(i), load_flags(u), vbits(0), encoding(enc) {} ++ unsigned operator()(int nbits, unsigned *bytes=nullptr); ++ private: ++- IMFILE *ifp; +++ rtengine::IMFILE *ifp; ++ unsigned &load_flags; ++ uchar buf[0x4000]; ++ int vbits; ++diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc ++index 7dde668eb..e551c9aad 100644 ++--- a/rtengine/dfmanager.cc +++++ b/rtengine/dfmanager.cc ++@@ -540,7 +540,7 @@ std::vector *DFManager::getHotPixels ( const std::string &mak, const std ++ ++ int DFManager::scanBadPixelsFile( Glib::ustring filename ) ++ { ++- FILE *file = fopen( filename.c_str(), "r" ); +++ FILE *file = ::fopen( filename.c_str(), "r" ); ++ ++ if( !file ) { ++ return false; ++diff --git a/rtengine/myfile.cc b/rtengine/myfile.cc ++index 842766dcf..2321d18bb 100644 ++--- a/rtengine/myfile.cc +++++ b/rtengine/myfile.cc ++@@ -70,7 +70,7 @@ int munmap(void *start, size_t length) ++ ++ #ifdef MYFILE_MMAP ++ ++-IMFILE* fopen (const char* fname) +++rtengine::IMFILE* rtengine::fopen (const char* fname) ++ { ++ int fd; ++ ++@@ -123,13 +123,13 @@ IMFILE* fopen (const char* fname) ++ return mf; ++ } ++ ++-IMFILE* gfopen (const char* fname) +++rtengine::IMFILE* rtengine::gfopen (const char* fname) ++ { ++ return fopen(fname); ++ } ++ #else ++ ++-IMFILE* fopen (const char* fname) +++rtengine::IMFILE* rtengine::fopen (const char* fname) ++ { ++ ++ FILE* f = g_fopen (fname, "rb"); ++@@ -152,7 +152,7 @@ IMFILE* fopen (const char* fname) ++ return mf; ++ } ++ ++-IMFILE* gfopen (const char* fname) +++rtengine::IMFILE* rtengine::gfopen (const char* fname) ++ { ++ ++ FILE* f = g_fopen (fname, "rb"); ++@@ -176,7 +176,7 @@ IMFILE* gfopen (const char* fname) ++ } ++ #endif //MYFILE_MMAP ++ ++-IMFILE* fopen (unsigned* buf, int size) +++rtengine::IMFILE* rtengine::fopen (unsigned* buf, int size) ++ { ++ ++ IMFILE* mf = new IMFILE; ++@@ -190,7 +190,7 @@ IMFILE* fopen (unsigned* buf, int size) ++ return mf; ++ } ++ ++-void fclose (IMFILE* f) +++void rtengine::fclose (IMFILE* f) ++ { ++ #ifdef MYFILE_MMAP ++ ++@@ -207,7 +207,7 @@ void fclose (IMFILE* f) ++ delete f; ++ } ++ ++-int fscanf (IMFILE* f, const char* s ...) +++int rtengine::fscanf (IMFILE* f, const char* s ...) ++ { ++ // fscanf not easily wrapped since we have no terminating \0 at end ++ // of file data and vsscanf() won't tell us how many characters that ++@@ -253,7 +253,7 @@ int fscanf (IMFILE* f, const char* s ...) ++ } ++ ++ ++-char* fgets (char* s, int n, IMFILE* f) +++char* rtengine::fgets (char* s, int n, IMFILE* f) ++ { ++ ++ if (f->pos >= f->size) { ++@@ -270,7 +270,7 @@ char* fgets (char* s, int n, IMFILE* f) ++ return s; ++ } ++ ++-void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) +++void rtengine::imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) ++ { ++ f->plistener = plistener; ++ f->progress_range = progress_range; ++@@ -278,7 +278,7 @@ void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, doub ++ f->progress_current = 0; ++ } ++ ++-void imfile_update_progress(IMFILE *f) +++void rtengine::imfile_update_progress(IMFILE *f) ++ { ++ if (!f->plistener || f->progress_current < f->progress_next) { ++ return; ++diff --git a/rtengine/myfile.h b/rtengine/myfile.h ++index 34b90c525..ae14ce31a 100644 ++--- a/rtengine/myfile.h +++++ b/rtengine/myfile.h ++@@ -30,8 +30,6 @@ namespace rtengine ++ ++ class ProgressListener; ++ ++-} ++- ++ struct IMFILE { ++ int fd; ++ ssize_t pos; ++@@ -141,3 +139,5 @@ inline unsigned char* fdata(int offset, IMFILE* f) ++ ++ int fscanf (IMFILE* f, const char* s ...); ++ char* fgets (char* s, int n, IMFILE* f); +++ +++} ++diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc ++index 8dc998862..cf500474f 100644 ++--- a/rtengine/rtthumbnail.cc +++++ b/rtengine/rtthumbnail.cc ++@@ -1965,7 +1965,7 @@ bool Thumbnail::writeImage (const Glib::ustring& fname) ++ ++ Glib::ustring fullFName = fname + ".rtti"; ++ ++- FILE* f = g_fopen (fullFName.c_str (), "wb"); +++ FILE* f = ::g_fopen (fullFName.c_str (), "wb"); ++ ++ if (!f) { ++ return false; ++@@ -2008,7 +2008,7 @@ bool Thumbnail::readImage (const Glib::ustring& fname) ++ return false; ++ } ++ ++- FILE* f = g_fopen(fullFName.c_str (), "rb"); +++ FILE* f = ::g_fopen(fullFName.c_str (), "rb"); ++ ++ if (!f) { ++ return false; ++@@ -2239,7 +2239,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) ++ return false; ++ } ++ ++- FILE *f = g_fopen (fname.c_str (), "wt"); +++ FILE *f = ::g_fopen (fname.c_str (), "wt"); ++ ++ if (!f) { ++ if (settings->verbose) { ++@@ -2262,7 +2262,7 @@ bool Thumbnail::readEmbProfile (const Glib::ustring& fname) ++ embProfile = nullptr; ++ embProfileLength = 0; ++ ++- FILE* f = g_fopen (fname.c_str (), "rb"); +++ FILE* f = ::g_fopen (fname.c_str (), "rb"); ++ ++ if (f) { ++ if (!fseek (f, 0, SEEK_END)) { ++@@ -2290,7 +2290,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) ++ { ++ ++ if (embProfileData) { ++- FILE* f = g_fopen (fname.c_str (), "wb"); +++ FILE* f = ::g_fopen (fname.c_str (), "wb"); ++ ++ if (f) { ++ fwrite (embProfileData, 1, embProfileLength, f); +diff -udHrN -- a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc +--- a/rtengine/canon_cr3_decoder.cc 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/canon_cr3_decoder.cc 2021-08-07 11:43:50.725202017 +0200 +@@ -662,7 +662,7 @@ + #endif + + struct LibRaw_abstract_datastream { +- IMFILE* ifp; ++ rtengine::IMFILE* ifp; + + void lock() + { +diff -udHrN -- a/rtengine/dcraw.cc b/rtengine/dcraw.cc +--- a/rtengine/dcraw.cc 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/dcraw.cc 2021-08-07 11:43:50.736202141 +0200 +@@ -2025,7 +2025,7 @@ + #endif + { + int len[2], pred[2]; +- IMFILE ifpthr = *ifp; ++ rtengine::IMFILE ifpthr = *ifp; + ifpthr.plistener = nullptr; + + #ifdef _OPENMP +@@ -3380,7 +3380,7 @@ + { + uchar *data = new (std::nothrow) uchar[raw_width + 1]; + merror(data, "sony_arw2_load_raw()"); +- IMFILE ifpthr = *ifp; ++ rtengine::IMFILE ifpthr = *ifp; + int pos = ifpthr.pos; + ushort pix[16]; + +@@ -6394,7 +6394,7 @@ + unsigned sony_curve[] = { 0,0,0,0,0,4095 }; + unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; + struct jhead jh; +-/*RT*/ IMFILE *sfp; ++/*RT*/ rtengine::IMFILE *sfp; + /*RT*/ int pana_raw = 0; + + if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) +@@ -6958,7 +6958,7 @@ + fread (buf, sony_length, 1, ifp); + sony_decrypt (buf, sony_length/4, 1, sony_key); + sfp = ifp; +-/*RT*/ ifp = fopen (buf, sony_length); ++/*RT*/ ifp = rtengine::fopen (buf, sony_length); + // if ((ifp = tmpfile())) { + // fwrite (buf, sony_length, 1, ifp); + // fseek (ifp, 0, SEEK_SET); +@@ -7264,7 +7264,7 @@ + { + const char *file, *ext; + char *jname, *jfile, *jext; +-/*RT*/ IMFILE *save=ifp; ++/*RT*/ rtengine::IMFILE *save=ifp; + + ext = strrchr (ifname, '.'); + file = strrchr (ifname, '/'); +@@ -7292,7 +7292,7 @@ + *jext = '0'; + } + if (strcmp (jname, ifname)) { +-/*RT*/ if ((ifp = fopen (jname))) { ++/*RT*/ if ((ifp = rtengine::fopen (jname))) { + // if ((ifp = fopen (jname, "rb"))) { + if (verbose) + fprintf (stderr,_("Reading metadata from %s ...\n"), jname); +diff -udHrN -- a/rtengine/dcraw.h b/rtengine/dcraw.h +--- a/rtengine/dcraw.h 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/dcraw.h 2021-08-07 11:43:50.737202152 +0200 +@@ -73,7 +73,7 @@ + + protected: + int exif_base, ciff_base, ciff_len; +- IMFILE *ifp; ++ rtengine::IMFILE *ifp; + FILE *ofp; + short order; + const char *ifname; +@@ -125,7 +125,7 @@ + int cur_buf_size; // buffer size + uchar *cur_buf; // currently read block + int fillbytes; // Counter to add extra byte for block size N*16 +- IMFILE *input; ++ rtengine::IMFILE *input; + struct int_pair grad_even[3][41]; // tables of gradients + struct int_pair grad_odd[3][41]; + ushort *linealloc; +@@ -278,7 +278,7 @@ + class getbithuff_t + { + public: +- getbithuff_t(DCraw *p,IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){} ++ getbithuff_t(DCraw *p,rtengine::IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){} + unsigned operator()(int nbits, ushort *huff); + + private: +@@ -288,7 +288,7 @@ + DCraw *parent; + unsigned bitbuf; + int vbits, reset; +- IMFILE *&ifp; ++ rtengine::IMFILE *&ifp; + unsigned &zero_after_ff; + }; + getbithuff_t getbithuff; +@@ -296,7 +296,7 @@ + class nikbithuff_t + { + public: +- explicit nikbithuff_t(IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){} ++ explicit nikbithuff_t(rtengine::IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){} + void operator()() {bitbuf = vbits = 0;}; + unsigned operator()(int nbits, ushort *huff); + unsigned errorCount() { return errors; } +@@ -309,7 +309,7 @@ + } + unsigned bitbuf, errors; + int vbits; +- IMFILE *&ifp; ++ rtengine::IMFILE *&ifp; + }; + nikbithuff_t nikbithuff; + +@@ -378,7 +378,7 @@ + // ph1_bithuff(int nbits, ushort *huff); + class ph1_bithuff_t { + public: +- ph1_bithuff_t(DCraw *p, IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){} ++ ph1_bithuff_t(DCraw *p, rtengine::IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){} + unsigned operator()(int nbits, ushort *huff); + unsigned operator()(int nbits); + unsigned operator()(); +@@ -412,7 +412,7 @@ + } + + short ℴ +- IMFILE* const ifp; ++ rtengine::IMFILE* const ifp; + UINT64 bitbuf; + int vbits; + }; +@@ -430,11 +430,11 @@ + + class pana_bits_t{ + public: +- pana_bits_t(IMFILE *i, unsigned &u, unsigned enc): ++ pana_bits_t(rtengine::IMFILE *i, unsigned &u, unsigned enc): + ifp(i), load_flags(u), vbits(0), encoding(enc) {} + unsigned operator()(int nbits, unsigned *bytes=nullptr); + private: +- IMFILE *ifp; ++ rtengine::IMFILE *ifp; + unsigned &load_flags; + uchar buf[0x4000]; + int vbits; +diff -udHrN -- a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc +--- a/rtengine/dfmanager.cc 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/dfmanager.cc 2021-08-07 11:43:50.738202163 +0200 +@@ -540,7 +540,7 @@ + + int DFManager::scanBadPixelsFile( Glib::ustring filename ) + { +- FILE *file = fopen( filename.c_str(), "r" ); ++ FILE *file = ::fopen( filename.c_str(), "r" ); + + if( !file ) { + return false; +diff -udHrN -- a/rtengine/myfile.cc b/rtengine/myfile.cc +--- a/rtengine/myfile.cc 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/myfile.cc 2021-08-07 11:43:50.738202163 +0200 +@@ -70,7 +70,7 @@ + + #ifdef MYFILE_MMAP + +-IMFILE* fopen (const char* fname) ++rtengine::IMFILE* rtengine::fopen (const char* fname) + { + int fd; + +@@ -123,13 +123,13 @@ + return mf; + } + +-IMFILE* gfopen (const char* fname) ++rtengine::IMFILE* rtengine::gfopen (const char* fname) + { + return fopen(fname); + } + #else + +-IMFILE* fopen (const char* fname) ++rtengine::IMFILE* rtengine::fopen (const char* fname) + { + + FILE* f = g_fopen (fname, "rb"); +@@ -152,7 +152,7 @@ + return mf; + } + +-IMFILE* gfopen (const char* fname) ++rtengine::IMFILE* rtengine::gfopen (const char* fname) + { + + FILE* f = g_fopen (fname, "rb"); +@@ -176,7 +176,7 @@ + } + #endif //MYFILE_MMAP + +-IMFILE* fopen (unsigned* buf, int size) ++rtengine::IMFILE* rtengine::fopen (unsigned* buf, int size) + { + + IMFILE* mf = new IMFILE; +@@ -190,7 +190,7 @@ + return mf; + } + +-void fclose (IMFILE* f) ++void rtengine::fclose (IMFILE* f) + { + #ifdef MYFILE_MMAP + +@@ -207,7 +207,7 @@ + delete f; + } + +-int fscanf (IMFILE* f, const char* s ...) ++int rtengine::fscanf (IMFILE* f, const char* s ...) + { + // fscanf not easily wrapped since we have no terminating \0 at end + // of file data and vsscanf() won't tell us how many characters that +@@ -253,7 +253,7 @@ + } + + +-char* fgets (char* s, int n, IMFILE* f) ++char* rtengine::fgets (char* s, int n, IMFILE* f) + { + + if (f->pos >= f->size) { +@@ -270,7 +270,7 @@ + return s; + } + +-void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) ++void rtengine::imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) + { + f->plistener = plistener; + f->progress_range = progress_range; +@@ -278,7 +278,7 @@ + f->progress_current = 0; + } + +-void imfile_update_progress(IMFILE *f) ++void rtengine::imfile_update_progress(IMFILE *f) + { + if (!f->plistener || f->progress_current < f->progress_next) { + return; +diff -udHrN -- a/rtengine/myfile.h b/rtengine/myfile.h +--- a/rtengine/myfile.h 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/myfile.h 2021-08-07 11:43:50.739202175 +0200 +@@ -30,8 +30,6 @@ + + class ProgressListener; + +-} +- + struct IMFILE { + int fd; + ssize_t pos; +@@ -141,3 +139,5 @@ + + int fscanf (IMFILE* f, const char* s ...); + char* fgets (char* s, int n, IMFILE* f); ++ ++} +diff -udHrN -- a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc +--- a/rtengine/rtthumbnail.cc 2020-02-04 07:39:52.000000000 +0100 ++++ b/rtengine/rtthumbnail.cc 2021-08-07 12:02:02.091503230 +0200 +@@ -1922,7 +1922,7 @@ + + Glib::ustring fullFName = fname + ".rtti"; + +- FILE* f = g_fopen (fullFName.c_str (), "wb"); ++ FILE* f = ::g_fopen (fullFName.c_str (), "wb"); + + if (!f) { + return false; +@@ -1965,7 +1965,7 @@ + return false; + } + +- FILE* f = g_fopen(fullFName.c_str (), "rb"); ++ FILE* f = ::g_fopen(fullFName.c_str (), "rb"); + + if (!f) { + return false; +@@ -2191,7 +2191,7 @@ + return false; + } + +- FILE *f = g_fopen (fname.c_str (), "wt"); ++ FILE *f = ::g_fopen (fname.c_str (), "wt"); + + if (!f) { + if (settings->verbose) { +@@ -2214,7 +2214,7 @@ + embProfile = nullptr; + embProfileLength = 0; + +- FILE* f = g_fopen (fname.c_str (), "rb"); ++ FILE* f = ::g_fopen (fname.c_str (), "rb"); + + if (f) { + if (!fseek (f, 0, SEEK_END)) { +@@ -2242,7 +2242,7 @@ + { + + if (embProfileData) { +- FILE* f = g_fopen (fname.c_str (), "wb"); ++ FILE* f = ::g_fopen (fname.c_str (), "wb"); + + if (f) { + fwrite (embProfileData, 1, embProfileLength, f); +@@ -2257,7 +2257,7 @@ + bool Thumbnail::readAEHistogram (const Glib::ustring& fname) + { + +- FILE* f = g_fopen(fname.c_str(), "rb"); ++ FILE* f = ::g_fopen(fname.c_str(), "rb"); + + if (!f) { + aeHistogram.reset(); +@@ -2280,7 +2280,7 @@ + { + + if (aeHistogram) { +- FILE* f = g_fopen (fname.c_str (), "wb"); ++ FILE* f = ::g_fopen (fname.c_str (), "wb"); + + if (f) { + fwrite (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof (aeHistogram[0]), f); diff --git a/RT_5.8_system_klt.patch b/RT_5.8_system_klt.patch new file mode 100644 index 0000000..d6b12b6 --- /dev/null +++ b/RT_5.8_system_klt.patch @@ -0,0 +1,49 @@ +From 9205b506b50c941ee13c78243f51a2e15d9fe16f Mon Sep 17 00:00:00 2001 +From: Mattia Verga +Date: Sun, 24 Nov 2019 13:48:12 +0100 +Subject: [PATCH] Fix linking against system klt + +--- + rtengine/CMakeLists.txt | 6 ++++++ + rtengine/calc_distort.cc | 4 ++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt +index f58afde5e..711818a6d 100644 +--- a/rtengine/CMakeLists.txt ++++ b/rtengine/CMakeLists.txt +@@ -12,6 +12,11 @@ include_directories(${EXTRA_INCDIR} + ${LENSFUN_INCLUDE_DIRS} + ${RSVG_INCLUDE_DIRS} + ) ++if(NOT WITH_SYSTEM_KLT) ++ include_directories("${CMAKE_SOURCE_DIR}/rtengine/klt") ++else() ++ include_directories(${KLT_INCLUDE_DIRS}) ++endif() + + link_directories("${PROJECT_SOURCE_DIR}/rtexif" + ${EXPAT_LIBRARY_DIRS} +@@ -184,6 +189,7 @@ target_link_libraries(rtengine rtexif + ${ZLIB_LIBRARIES} + ${LENSFUN_LIBRARIES} + ${RSVG_LIBRARIES} ++ ${KLT_LIBRARIES} + ) + + install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +diff --git a/rtengine/calc_distort.cc b/rtengine/calc_distort.cc +index 7af47adb2..3a7a4a1c4 100644 +--- a/rtengine/calc_distort.cc ++++ b/rtengine/calc_distort.cc +@@ -5,8 +5,8 @@ locations (before and after tracking) to text files and to PPM files, + and prints the features to the screen. + **********************************************************************/ + +-#include "klt/pnmio.h" +-#include "klt/klt.h" ++#include ++#include + #include + #include + diff --git a/ReleaseInfo.cmake b/ReleaseInfo.cmake deleted file mode 100644 index 6b0573f..0000000 --- a/ReleaseInfo.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set(GIT_DESCRIBE 5.9) -set(GIT_BRANCH dev) -set(GIT_COMMIT 4059ae5) -set(GIT_COMMIT_DATE 2022-10-02) -set(GIT_COMMITS_SINCE_TAG 0) -set(GIT_COMMITS_SINCE_BRANCH 0) -set(GIT_VERSION_NUMERIC_BS 0.0.0) diff --git a/create_ReleaseInfo.sh b/create_ReleaseInfo.sh deleted file mode 100755 index 77079f7..0000000 --- a/create_ReleaseInfo.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# example usage: ./create_ReleaseInfo.sh 5.9 68ec1a5 2022-05-25 - -VERSION=$1 -SHORTCOMMIT=$2 -DATE=$3 - -echo "set(GIT_DESCRIBE $VERSION)" > ReleaseInfo.cmake -echo "set(GIT_BRANCH dev)" >> ReleaseInfo.cmake -echo "set(GIT_COMMIT $SHORTCOMMIT)" >> ReleaseInfo.cmake -echo "set(GIT_COMMIT_DATE $DATE)" >> ReleaseInfo.cmake -echo "set(GIT_COMMITS_SINCE_TAG 0)" >> ReleaseInfo.cmake -echo "set(GIT_COMMITS_SINCE_BRANCH 0)" >> ReleaseInfo.cmake -echo "set(GIT_VERSION_NUMERIC_BS 0.0.0)" >> ReleaseInfo.cmake diff --git a/rawtherapee.spec b/rawtherapee.spec index 5069323..75a5797 100644 --- a/rawtherapee.spec +++ b/rawtherapee.spec @@ -1,40 +1,32 @@ %global link_tcmalloc 1 -%global development 0 - -%if 0%{?development} -%global commit 4059ae5bcad8e18443bf8f37bcff84de1dcc0d03 -%global shortcommit %(c=%{commit}; echo ${c:0:7}) -%endif - -# https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval -ExcludeArch: %{ix86} Name: rawtherapee -%if 0%{?development} -Version: 5.9~20221002git%{shortcommit} -%else -Version: 5.12 -%endif +Version: 5.8 Release: %autorelease Summary: Raw image processing software -License: GPL-3.0-or-later and AGPL-3.0-or-later and MIT-open-group and IJG and BSL-1.0 and Apache-2.0 +License: GPLv3 and MIT and IJG URL: http://www.rawtherapee.com/ +Source0: https://github.com/Beep6581/RawTherapee/releases/download/%{version}/%{name}-%{version}.tar.xz -%if 0%{?development} -Source0: https://github.com/Beep6581/RawTherapee/archive/%{commit}/RawTherapee-%{commit}.tar.gz -# File created with ./create_ReleaseInfo.sh 5.9 4059ae5 2022-10-02 -Source1: create_ReleaseInfo.sh -Source2: ReleaseInfo.cmake -%else -#Source0: https://rawtherapee.com/shared/source/%%{name}-%%{version}.tar.xz -Source0: https://github.com/Beep6581/RawTherapee/releases/download/%{version}/rawtherapee-%{version}.tar.xz -%endif +# Fix linking against system's KLT +# Upstream PR https://github.com/Beep6581/RawTherapee/pull/5539 +Patch: RT_5.8_system_klt.patch -# Patch to fix segfault at startup -# See upstream ticket https://github.com/RawTherapee/RawTherapee/issues/7532 -Patch: 0001-Fix-static-init-order-fiasco-crashes.patch -Patch: 0001-Fix-typos.patch +# Backport patch for fixing rhbz#1820907 +Patch: RT_5.8_fix_crop.patch + +# Backport patch for fixing build with glibc 2.34 +# https://github.com/Beep6581/RawTherapee/issues/6324 +Patch: RT_5.8_glibc234.patch + +# Backport patch for fixing Canon sRAW/mRAW +# https://github.com/Beep6581/RawTherapee/issues/5898 +Patch: RT_5.8_fix_canon_sraw.patch + +# Backport patch for fixing Nikon Z EXIF information +# https://github.com/Beep6581/RawTherapee/issues/5808 +Patch: RT_5.8_fix_nikon_z_exif.patch BuildRequires: cmake BuildRequires: desktop-file-utils @@ -43,22 +35,20 @@ BuildRequires: klt-devel BuildRequires: libappstream-glib BuildRequires: libatomic -BuildRequires: pkgconfig(exiv2) >= 0.24 -BuildRequires: pkgconfig(expat) >= 2.1 +BuildRequires: pkgconfig(exiv2) +BuildRequires: pkgconfig(expat) BuildRequires: pkgconfig(fftw3f) -BuildRequires: pkgconfig(glib-2.0) >= 2.48 -BuildRequires: pkgconfig(glibmm-2.4) >= 2.48 -BuildRequires: pkgconfig(gtk+-3.0) >= 3.24.3 +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(glibmm-2.4) +BuildRequires: pkgconfig(gtk+-3.0) BuildRequires: pkgconfig(gtkmm-3.0) -BuildRequires: pkgconfig(lcms2) >= 2.6 -BuildRequires: pkgconfig(lensfun) >= 0.2 +BuildRequires: pkgconfig(lcms2) +BuildRequires: pkgconfig(lensfun) BuildRequires: pkgconfig(libcanberra) BuildRequires: pkgconfig(libiptcdata) BuildRequires: pkgconfig(libjpeg) -BuildRequires: pkgconfig(libjxl) BuildRequires: pkgconfig(libpng) -BuildRequires: pkgconfig(libraw) -BuildRequires: pkgconfig(librsvg-2.0) >= 2.52 +BuildRequires: pkgconfig(librsvg-2.0) %if 0%{?link_tcmalloc} BuildRequires: pkgconfig(libtcmalloc) %endif @@ -79,32 +69,30 @@ many parameters to enhance the raw picture before finally exporting it to some common image format. %prep -%if 0%{?development} -%autosetup -p1 -n RawTherapee-%{commit} -cp -p %SOURCE2 . -%else %autosetup -p1 -n %{name}-%{version} -%endif + +# fix wrong line endings +sed -i "s|\r||g" LICENSE.txt # remove bundled KLT, so we're sure to use system provided KLT rm -rf rtengine/klt/ -# remove bundled libraw, so we're sure to use system provided libraw -rm -rf rtengine/libraw/ - %build # do not build shared libs # https://github.com/Beep6581/RawTherapee/pull/5479 -%{cmake} \ - -DCMAKE_BUILD_TYPE=release \ +%{cmake} %{?BUILD_TESTS} \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DLIBDIR=%{_libdir} \ + -DCMAKE_BUILD_TYPE=release \ -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DAUTOMATED_BUILD_SYSTEM:BOOL=ON \ + -DCACHE_NAME_SUFFIX="" \ + -DCMAKE_CXX_FLAGS="$RPM_OPT_FLAGS" \ + -DCMAKE_C_FLAGS="$RPM_OPT_FLAGS" \ %if 0%{?link_tcmalloc} -DENABLE_TCMALLOC=ON \ %endif - -DWITH_SYSTEM_KLT=ON \ - -DWITH_SYSTEM_LIBRAW="ON" \ - -DWITH_JXL="ON" + -DWITH_SYSTEM_KLT=ON %cmake_build @@ -123,8 +111,7 @@ appstream-util validate-relax --nonet %{buildroot}/%{_datadir}/metainfo/com.%{na %files -%doc AUTHORS.txt RELEASE_NOTES.txt -%license LICENSE licenses/DroidSansMonoDotted.txt licenses/sleef_LICENSE.txt licenses/jdatasrc +%doc AUTHORS.txt LICENSE.txt RELEASE_NOTES.txt %{_mandir}/man1/%{name}.1.gz %{_bindir}/%{name} %{_bindir}/%{name}-cli @@ -132,7 +119,6 @@ appstream-util validate-relax --nonet %{buildroot}/%{_datadir}/metainfo/com.%{na %{_datadir}/applications/%{name}.desktop %{_datadir}/metainfo/com.%{name}.RawTherapee.appdata.xml %{_datadir}/icons/hicolor/*/apps/%{name}.png -%{_datadir}/icons/hicolor/scalable/apps/%{name}.svg %changelog diff --git a/sources b/sources index 56607ae..90ce232 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (rawtherapee-5.12.tar.xz) = 0590a0852385bc85be2a33e5f978904f3a05385b5702f8960adb5aade67d549037245506c84a541d8a49bcc49fe7b71c765be875336cb86deb5c03fd4e3f4c23 +SHA512 (rawtherapee-5.8.tar.xz) = bc79586cd937dcaefc053e65faa2162de887d514e44980956d937c157c6d55c4f6e6a7a9b8f91f2d657ed2054814737b96d5d741674c1e5a961d7177433efe4e