public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Mattia Verga <mattia.verga@proton.me>
To: git-commits@fedoraproject.org
Subject: [rpms/rawtherapee] f44: Update to 5.13 (Fedora#2491090)
Date: Sun, 02 Aug 2026 11:47:55 GMT	[thread overview]
Message-ID: <178567127519.1.9310074674217912161.rpms-rawtherapee-20926a6e2522@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/rawtherapee
Branch : f44
Commit : 20926a6e25228d457f45349e29edc5a054083624
Author : Mattia Verga <mattia.verga@proton.me>
Date   : 2026-08-02T13:29:52+02:00
Stats  : +16/-5857 in 5 file(s)
URL    : https://src.fedoraproject.org/rpms/rawtherapee/c/20926a6e25228d457f45349e29edc5a054083624?branch=f44

Log:
Update to 5.13 (Fedora#2491090)

---
diff --git a/.gitignore b/.gitignore
index a049e4f..e7c4abe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,4 @@ rawtherapee-3.0-a1.tar.bz2
 /rawtherapee-5.11.tar.xz
 /rawtherapee-5.12-rc1.tar.xz
 /rawtherapee-5.12.tar.xz
+/rawtherapee-5.13.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 <daniel.gao.work@gmail.com>
-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::HaldCLUT> 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<Glib::ustring> dirs = {
--        rt_profile_dir,
--        Glib::build_filename(options.rtdir, "dcpprofiles")
--    };
-+    std::deque<Glib::ustring> 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::badPix>* 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<float> &rawData, array2D<float> &red, array2D<float> &green, array2D<float> &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 <daniel.gao.work@gmail.com>
-+ *
-+ *  RawTherapee is free software: you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License as published by
-+ *  the Free Software Foundation, either version 3 of the License, or
-+ *  (at your option) any later version.
-+ *
-+ *  RawTherapee is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
-+ */
-+
-+#include "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 <daniel.gao.work@gmail.com>
-+ *
-+ *  RawTherapee is free software: you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License as published by
-+ *  the Free Software Foundation, either version 3 of the License, or
-+ *  (at your option) any later version.
-+ *
-+ *  RawTherapee is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
-+ */
-+
-+#pragma once
-+
-+#include <glibmm/ustring.h>
-+
-+#include <memory>
-+
-+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<Options> 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<int>(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<BatchQueueEntry*>& 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<float>(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<Gtk::TextBuffer> 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<u><b>", text, "</b></u>\n"));
-@@ -403,6 +407,7 @@ void BatchQueuePanel::populateTemplateHelpBuffer(Glib::RefPtr<Gtk::TextBuffer> 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<pathElementCount; n++) {
-             auto path1 = Glib::ustring::format("%", letter, offset1+n*mult1);
-             auto path2 = Glib::ustring::format("%", letter, offset2+n*mult2);
-@@ -465,6 +470,7 @@ void BatchQueuePanel::addBatchQueueJobs(const std::vector<BatchQueueEntry*>& 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<FlatCurveEditor*>(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<GradientMilestone> 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<Cairo::Context> 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<Cairo::Context> 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<FlatCurveEditor*>(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<Gtk::TreeIter> 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<int> *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<int> *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<Gtk::Window*> (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<unsigned>(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<rtengine::IImagefloat*> *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<unsigned>(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 <gtk/gtk.h>
- #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<Glib::ustring> 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<FileBrowserEntry*> 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<FileBrowserEntry*> mselected)
- {
-     std::vector<Thumbnail*> 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<Cairo::Context> 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<Glib::ustring> &file_names,
-+    std::vector<Glib::RefPtr<Gio::File>> *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<Glib::ustring> FileCatalog::getFileList(std::vector<Glib::RefPtr<Gio::File>> *dirs_explored)
- {
--
-     std::vector<Glib::ustring> names;
- 
--    const std::set<std::string>& extensions = options.parsedExtensionsSet;
--
--    static void (*getFilesRecursively)(const Glib::ustring &, int, int &, std::vector<Glib::ustring> &, std::vector<Glib::RefPtr<Gio::File>> *) = [](const Glib::ustring &dir_path, int max_depth, int &dir_quota, std::vector<Glib::ustring> &file_names, std::vector<Glib::RefPtr<Gio::File>> * 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<Thumbnail*>& 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<FileBrowserEntry*>& 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<FileBrowserEntry*>& 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<FileBrowserEntry*>& 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<FileBrowserEntry*>& tbe, b
- 
- 
-                     // attempt to copy/move paramFile only if it exist next to the src
--                    Glib::RefPtr<Gio::File> scr_param = Gio::File::create_for_path (  src_fPath + paramFileExtension );
-+                    Glib::RefPtr<Gio::File> 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<Gio::File> 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<FileBrowserEntry*>& 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<FileBrowserEntry*>& 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<FileBrowserEntry*>& 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<Gio::File>& file, const Glib::RefPtr<Gio::File>& 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<rtengine::Initial
-         }
-     }
- 
-+    const auto& options = App::get().options();
-+
-     // The purpose of the pendingLoads vector is to open tabs in the same order as the loads where initiated. It has no effect on single editor mode.
-     while (pendingLoads.size() > 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<Gtk::TreeStore> &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<Gtk::TreeStore> &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<Cairo::Context> 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<std::uint8_t>(g),
-             static_cast<std::uint8_t>(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<Cairo::Context> &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<Cairo::Context> &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<std::uint8_t>(g),
-             static_cast<std::uint8_t>(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<FlatCurveEditor*>(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("&lt;") == Glib::ustring::npos && tt.find("&gt;") == 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<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(llCurveEditorG->addCurve(CT_Diagonal, "L(L)"))),
-     ccshape(static_cast<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(clCurveEditorG->addCurve(CT_Diagonal, "C(L)"))),
-     lcshape(static_cast<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskshape(static_cast<FlatCurveEditor*>(maskCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskshape(static_cast<FlatCurveEditor *>(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<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskexpCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskexpshape(static_cast<FlatCurveEditor*>(maskexpCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskexpshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskSHCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskSHshape(static_cast<FlatCurveEditor*>(maskSHCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskSHshape(static_cast<FlatCurveEditor*>(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<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskvibCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskvibshape(static_cast<FlatCurveEditor*>(maskvibCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskvibshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(maskblCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskblshape(static_cast<FlatCurveEditor*>(maskblCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskblshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(masktmCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmasktmshape(static_cast<FlatCurveEditor*>(masktmCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmasktmshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(maskretiCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskretishape(static_cast<FlatCurveEditor*>(maskretiCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskretishape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(masklcCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmasklcshape(static_cast<FlatCurveEditor*>(masklcCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmasklcshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskcbCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
- LLmaskcbshape(static_cast<FlatCurveEditor*>(maskcbCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
- HHmaskcbshape(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(maskCurveEditorL->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskshapeL(static_cast<FlatCurveEditor*>(maskCurveEditorL->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskshapeL(static_cast<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(mask_CurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmask_shape(static_cast<FlatCurveEditor*>(mask_CurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmask_shape(static_cast<FlatCurveEditor *>(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<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<FlatCurveEditor*>(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<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(jz1CurveEditorG->addCurve(CT_Diagonal, "Jz(J)"))),
-     shapecz(static_cast<DiagonalCurveEditor*>(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<DiagonalCurveEditor*>(jz1CurveEditorG->addCurve(CT_Diagonal, "Cz(J)"))),
-     HHshapejz(static_cast<FlatCurveEditor*>(jz3CurveEditorG->addCurve(CT_Flat, "Hz(Hz)", nullptr, false, true))),
-     CHshapejz(static_cast<FlatCurveEditor*>(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<FlatCurveEditor*>(maskcieCurveEditorG->addCurve(CT_Flat, "C", nullptr, false, false))),
-     LLmaskcieshape(static_cast<FlatCurveEditor*>(maskcieCurveEditorG->addCurve(CT_Flat, "L", nullptr, false, false))),
-     HHmaskcieshape(static_cast<FlatCurveEditor*>(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<FlatCurveEditor *>(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<DiagonalCurveEditor*>(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<FlatCurveEditor*>(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<Pango::Context> 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<std::uint8_t>(255 * g),
-         static_cast<std::uint8_t>(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<Gtk::IconTheme> 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<char *> (argv0.c_str()) };
-+    if (fatalError.empty() && app.isRemote()) {
-+        char *app_argv[2] = { const_cast<char *> (app.argv0().c_str()) };
-         int app_argc = 1;
- 
--        if (!argv1.empty()) {
-+        if (!app.argv1().empty()) {
-             app_argc = 2;
--            app_argv[1] = const_cast<char *> (argv1.c_str());
-+            app_argv[1] = const_cast<char *> (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> 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<std::uint8_t>(g),
-                         static_cast<std::uint8_t>(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<double> (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 <Language> for each locale <Language> (<LC>) -- 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<Glib::ustring> 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<std::string> 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 <gtkmm/enums.h>
- #endif
-+#include "rtengine/rtapp.h"
- #include "rtengine/settings.h"
- #include <exception>
- 
-@@ -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<rtengine::procparams::ProcParams>&
- 
- 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<Gio::File> 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<Gtk::TreeSelection> 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<Glib::ustring>::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<Gtk::CssProvider> themecss;
- Glib::RefPtr<Gtk::CssProvider> 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<Glib::ustring> 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<Gtk::FileFilter> 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<Gtk::FileFilter> 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<GradientMilestone> 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 <iostream>
- #include <librsvg/rsvg.h>
- 
-+#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<Cairo::ImageSurface> 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<Cairo::ImageSurface> 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<RTWindow*>(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<Gdk::Screen> 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<int> &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::vector<E
-         panel.second->updateExternalEditorWidget(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 <glib/gstdio.h>
- 
- #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<Glib::ustring, bool> 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<float>(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<GradientMilestone> 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 <daniel.gao.work@gmail.com>
-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/rawtherapee.spec b/rawtherapee.spec
index 5069323..3ce079f 100644
--- a/rawtherapee.spec
+++ b/rawtherapee.spec
@@ -13,7 +13,7 @@ Name:           rawtherapee
 %if 0%{?development}
 Version:        5.9~20221002git%{shortcommit}
 %else
-Version:        5.12
+Version:        5.13
 %endif
 Release:        %autorelease
 Summary:        Raw image processing software
@@ -31,10 +31,6 @@ Source2:        ReleaseInfo.cmake
 Source0:        https://github.com/Beep6581/RawTherapee/releases/download/%{version}/rawtherapee-%{version}.tar.xz
 %endif
 
-# 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
 
 BuildRequires:  cmake
 BuildRequires:  desktop-file-utils
@@ -46,6 +42,7 @@ BuildRequires:  libatomic
 BuildRequires:  pkgconfig(exiv2) >= 0.24
 BuildRequires:  pkgconfig(expat) >= 2.1
 BuildRequires:  pkgconfig(fftw3f)
+BuildRequires:  pkgconfig(fmt)
 BuildRequires:  pkgconfig(glib-2.0) >= 2.48
 BuildRequires:  pkgconfig(glibmm-2.4) >= 2.48
 BuildRequires:  pkgconfig(gtk+-3.0) >= 3.24.3
@@ -104,6 +101,7 @@ rm -rf rtengine/libraw/
 %endif
         -DWITH_SYSTEM_KLT=ON \
         -DWITH_SYSTEM_LIBRAW="ON" \
+        -DWITH_SYSTEM_FMT="ON" \
         -DWITH_JXL="ON"
 
 %cmake_build
@@ -114,7 +112,16 @@ rm -rf rtengine/libraw/
 
 
 # These file are taken from the root already
-rm -rf %{buildroot}/%{_datadir}/doc 
+rm -rf %{buildroot}%{_datadir}/doc
+# Remove license files which don't pertain to Fedora binaries
+# Font only installed on Windows builds
+rm -rf %{buildroot}%{_datadir}/licenses/%{name}/licenses/DroidSansMonoDotted.txt
+# These libraries are linked to system's provided
+# No need to install license files - https://github.com/RawTherapee/RawTherapee/issues/7718
+rm -rf %{buildroot}%{_datadir}/licenses/%{name}/licenses/{Expat,Lensfun,LibRaw,LunaSVG,cJSON,gtkmm,lcms2,libcanberra,libiptcdata,libjxl,librsvg,libtiff,tcmalloc}_LICENSE
+# Only related to OSX builds
+rm -rf %{buildroot}%{_datadir}/licenses/%{name}/licenses/osx_libiomp_LICENSE.txt
+
 
 
 %check
@@ -124,7 +131,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
+%license LICENSE licenses/sleef_LICENSE.txt licenses/jpeg_ijg_LICENSE
 %{_mandir}/man1/%{name}.1.gz
 %{_bindir}/%{name}
 %{_bindir}/%{name}-cli

diff --git a/sources b/sources
index 56607ae..2b1c086 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (rawtherapee-5.12.tar.xz) = 0590a0852385bc85be2a33e5f978904f3a05385b5702f8960adb5aade67d549037245506c84a541d8a49bcc49fe7b71c765be875336cb86deb5c03fd4e3f4c23
+SHA512 (rawtherapee-5.13.tar.xz) = ea2f4f5d748ca4c50214d1d68723e291830f7754656417a4c261ebbe5b757f8aa2afdbb2bf4be9906050de4cb1fd27861277a3f5df05b14386564344596f1ab5

                 reply	other threads:[~2026-08-02 11:47 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178567127519.1.9310074674217912161.rpms-rawtherapee-20926a6e2522@fedoraproject.org \
    --to=mattia.verga@proton.me \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox