Solving bug reported in issue 1341: "PP3 file cleanup" ...application's crash if the default raw or image profile didn't exist
This commit is contained in:
@@ -537,6 +537,8 @@ NAVIGATOR_S_VALUE;S = %1
|
||||
NAVIGATOR_V_NA;V = n/d
|
||||
NAVIGATOR_V_VALUE;V = %1
|
||||
NAVIGATOR_XY_NA;x = n/d, y = n/d
|
||||
OPTIONS_DEFRAW_MISSING;Le profil par défaut pour les <b>images Raw</b> n'a pas été trouvé ou n'a pas été réglé.\n\nVérifiez également le dossier de vos profils, il peut être manquant ou endommagé\n\nLes valeurs internes pas défaut seront utilisées.
|
||||
OPTIONS_DEFIMG_MISSING;Le profil par défaut pour les <b>images standards</b> n'a pas été trouvé ou n'a pas été réglé.\n\nVérifiez également le dossier de vos profils, il peut être manquant ou endommagé\n\nLes valeurs internes pas défaut seront utilisées.
|
||||
PARTIALPASTE_BASICGROUP;Réglages de base
|
||||
PARTIALPASTE_CACORRECTION;Aberration chromatique
|
||||
PARTIALPASTE_CHANNELMIXER;Mixage des canaux
|
||||
|
@@ -542,6 +542,8 @@ NAVIGATOR_S_VALUE;S = %1
|
||||
NAVIGATOR_V_NA;V = n/a
|
||||
NAVIGATOR_V_VALUE;V = %1
|
||||
NAVIGATOR_XY_NA;x = n/a, y = n/a
|
||||
OPTIONS_DEFRAW_MISSING;The default profile for raw images could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used.
|
||||
OPTIONS_DEFIMG_MISSING;The default profile for standard images could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used.
|
||||
PARTIALPASTE_BASICGROUP;Basic Settings
|
||||
PARTIALPASTE_CACORRECTION;C/A Correction
|
||||
PARTIALPASTE_CHANNELMIXER;Channel mixer
|
||||
|
@@ -11,6 +11,7 @@
|
||||
MultiUser=true
|
||||
|
||||
[File Browser]
|
||||
# Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include)
|
||||
ParseExtensions=arw;cr2;crf;crw;dng;jpg;kdc;mef;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwz;sr2;srw;tif;tiff;
|
||||
ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
|
||||
|
||||
@@ -21,3 +22,17 @@ PathTemplate=%p1/converted/%f
|
||||
# if this is set to a path of a custom program, it will receive the EXIFs as parameters and must generate a PP3 preset file for the given RAW/JPG
|
||||
# Parameters: <Path to RAW/JPG> <Path to default profile> <fNumber> <expose in seconds> <focal length in mm> <ISO> <Lens> <Camera>
|
||||
CustomProfileBuilder=
|
||||
|
||||
# Set here an absolute or relative path (to the rawtherapee.exe file) to the directory containing your own profiles.
|
||||
# If MultiUser=true, each user will have their own "options" file, and can set a common or different absolu path
|
||||
#Directory=profiles
|
||||
|
||||
# Uncomment and set UseBundledProfiles to false if you don't want to be polluted by RawTherapee's bundled profiles
|
||||
# Warning: if you don't set RawDefault and ImgDefault to one of your own profile, Internal values will be used instead
|
||||
#UseBundledProfiles=true
|
||||
|
||||
# Default profile name (without extension) to use for raw images
|
||||
#RawDefault=Default
|
||||
|
||||
# Default profile name (without extension) to use for standard (8bits) images
|
||||
#ImgDefault=Neutral
|
||||
|
@@ -11,6 +11,7 @@
|
||||
MultiUser=true
|
||||
|
||||
[File Browser]
|
||||
# Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include)
|
||||
ParseExtensions=arw;cr2;crf;crw;dng;jpg;kdc;mef;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwz;sr2;srw;tif;tiff;
|
||||
ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
|
||||
|
||||
@@ -21,3 +22,17 @@ PathTemplate=%p1/converted/%f
|
||||
# if this is set to a path of a custom program, it will receive the EXIFs as parameters and must generate a PP3 preset file for the given RAW/JPG
|
||||
# Parameters: <Path to RAW/JPG> <Path to default profile> <fNumber> <expose in seconds> <focal length in mm> <ISO> <Lens> <Camera>
|
||||
CustomProfileBuilder=
|
||||
|
||||
# Set here an absolute or relative path (to the rawtherapee.exe file) to the directory containing your own profiles.
|
||||
# If MultiUser=true, each user will have their own "options" file, and can set a common or different absolu path
|
||||
#Directory=profiles
|
||||
|
||||
# Uncomment and set UseBundledProfiles to false if you don't want to be polluted by RawTherapee's bundled profiles
|
||||
# Warning: if you don't set RawDefault and ImgDefault to one of your own profile, Internal values will be used instead
|
||||
#UseBundledProfiles=true
|
||||
|
||||
# Default profile name (without extension) to use for raw images
|
||||
#RawDefault=Default
|
||||
|
||||
# Default profile name (without extension) to use for standard (8bits) images
|
||||
#ImgDefault=Neutral
|
||||
|
@@ -13,6 +13,7 @@ MultiUser=true
|
||||
UseSystemTheme=false
|
||||
|
||||
[File Browser]
|
||||
# Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include)
|
||||
ParseExtensions=arw;cr2;crf;crw;dng;jpg;kdc;mef;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwz;sr2;srw;tif;tiff;
|
||||
ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
|
||||
|
||||
@@ -23,3 +24,17 @@ PathTemplate=%p1/converted/%f
|
||||
# if this is set to a path of a custom program, it will receive the EXIFs as parameters and must generate a PP3 preset file for the given RAW/JPG
|
||||
# Parameters: <Path to RAW/JPG> <Path to default profile> <fNumber> <expose in seconds> <focal length in mm> <ISO> <Lens> <Camera>
|
||||
CustomProfileBuilder=
|
||||
|
||||
# Set here an absolute or relative path (to the rawtherapee.exe file) to the directory containing your own profiles.
|
||||
# If MultiUser=true, each user will have their own "options" file, and can set a common or different absolu path
|
||||
#Directory=profiles
|
||||
|
||||
# Uncomment and set UseBundledProfiles to false if you don't want to be polluted by RawTherapee's bundled profiles
|
||||
# Warning: if you don't set RawDefault and ImgDefault to one of your own profile, Internal values will be used instead
|
||||
#UseBundledProfiles=true
|
||||
|
||||
# Default profile name (without extension) to use for raw images
|
||||
#RawDefault=Default
|
||||
|
||||
# Default profile name (without extension) to use for standard (8bits) images
|
||||
#ImgDefault=Neutral
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "dfmanager.h"
|
||||
#include "ffmanager.h"
|
||||
#include "rtthumbnail.h"
|
||||
#include "../rtgui/profilestore.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@@ -40,6 +41,7 @@ int init (const Settings* s, Glib::ustring baseDir) {
|
||||
|
||||
dcpStore->init (baseDir + "/dcpprofiles");
|
||||
|
||||
profileStore.init ();
|
||||
ProcParams::init ();
|
||||
CurveFactory::init ();
|
||||
ImProcFunctions::initMunsell();
|
||||
|
@@ -687,6 +687,9 @@ int ProcParams::write (Glib::ustring &fname, Glib::ustring &content) const {
|
||||
|
||||
int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) {
|
||||
|
||||
if (fname.empty())
|
||||
return 1;
|
||||
|
||||
SafeKeyFile keyFile;
|
||||
try {
|
||||
//setDefaults ();
|
||||
|
@@ -40,8 +40,6 @@ FileBrowser::FileBrowser ()
|
||||
fbih->destroyed = false;
|
||||
fbih->pending = 0;
|
||||
|
||||
// profileStore.parseProfiles ();
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &FileBrowser::styleChanged) );
|
||||
|
||||
int p = 0;
|
||||
|
@@ -159,7 +159,20 @@ int main(int argc, char **argv)
|
||||
|
||||
RTWindow *rtWindow = new class RTWindow();
|
||||
gdk_threads_enter ();
|
||||
|
||||
// alerting users if the default raw and image profiles are missing
|
||||
if (options.is_defProfRawMissing()) {
|
||||
Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFRAW_MISSING"), options.defProfRaw), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
msgd.run ();
|
||||
}
|
||||
if (options.is_defProfImgMissing()) {
|
||||
Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFIMG_MISSING"), options.defProfImg), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
msgd.run ();
|
||||
}
|
||||
|
||||
// opening the main window
|
||||
m.run(*rtWindow);
|
||||
|
||||
gdk_threads_leave ();
|
||||
delete rtWindow;
|
||||
rtengine::cleanup();
|
||||
@@ -348,16 +361,18 @@ int processLineParams( int argc, char **argv )
|
||||
|
||||
if (useDefault) {
|
||||
rawParams = new rtengine::procparams::PartialProfile(true);
|
||||
if (rawParams->load(options.profilePath+"/" + options.defProfRaw + paramFileExtension)) {
|
||||
std::cerr << "Error: default Raw procparams file \""<< (options.profilePath+"/" + options.defProfRaw + paramFileExtension) << "\" not found" << std::endl;
|
||||
Glib::ustring profPath = options.findProfilePath(options.defProfRaw);
|
||||
if (options.is_defProfRawMissing() || profPath.empty() || rawParams->load(Glib::build_filename(profPath, options.defProfRaw + paramFileExtension))) {
|
||||
std::cerr << "Error: default Raw procparams file not found" << std::endl;
|
||||
rawParams->deleteInstance();
|
||||
delete rawParams;
|
||||
deleteProcParams(processingParams);
|
||||
return -3;
|
||||
}
|
||||
imgParams = new rtengine::procparams::PartialProfile(true);
|
||||
if (imgParams->load(options.profilePath+"/" + options.defProfImg + paramFileExtension)) {
|
||||
std::cerr << "Error: default Image procparams file \""<< (options.profilePath+"/" + options.defProfImg + paramFileExtension) << "\" not found" << std::endl;
|
||||
profPath = options.findProfilePath(options.defProfImg);
|
||||
if (options.is_defProfImgMissing() || profPath.empty() || imgParams->load(Glib::build_filename(profPath, options.defProfImg + paramFileExtension))) {
|
||||
std::cerr << "Error: default Image procparams file not found" << std::endl;
|
||||
imgParams->deleteInstance();
|
||||
delete imgParams;
|
||||
rawParams->deleteInstance();
|
||||
|
163
rtgui/options.cc
163
rtgui/options.cc
@@ -42,11 +42,130 @@ Glib::ustring paramFileExtension = ".pp3";
|
||||
|
||||
Options::Options () {
|
||||
|
||||
defProfRawMissing = false;
|
||||
defProfImgMissing = false;
|
||||
setDefaults ();
|
||||
}
|
||||
|
||||
const char *DefaultLanguage = "English (US)";
|
||||
|
||||
inline bool Options::checkProfilePath(Glib::ustring &path) {
|
||||
if (path.empty())
|
||||
return false;
|
||||
|
||||
Glib::ustring p = getUserProfilePath();
|
||||
if (!p.empty() && safe_file_test (path+paramFileExtension, Glib::FILE_TEST_EXISTS))
|
||||
return true;
|
||||
|
||||
p = getGlobalProfilePath();
|
||||
if (!p.empty() && safe_file_test (path+paramFileExtension, Glib::FILE_TEST_EXISTS))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Options::checkDirPath(Glib::ustring &path, Glib::ustring errString) {
|
||||
if (safe_file_test (path, Glib::FILE_TEST_EXISTS) && safe_file_test (path, Glib::FILE_TEST_IS_DIR))
|
||||
return true;
|
||||
else {
|
||||
if (!errString.empty()) printf("%s\n", errString.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Options::updatePaths() {
|
||||
|
||||
Glib::ustring tmpPath;
|
||||
|
||||
userProfilePath = "";
|
||||
globalProfilePath = "";
|
||||
|
||||
if (Glib::path_is_absolute(profilePath)) {
|
||||
// absolute path
|
||||
if (!checkDirPath (profilePath, "")) {
|
||||
int retVal = safe_g_mkdir_with_parents (profilePath, 511);
|
||||
if (!retVal)
|
||||
printf("Error: user's profiles' directory \"%s\" creation failed\n", profilePath.c_str());
|
||||
}
|
||||
if (checkDirPath (profilePath, "Error: the specified user's profiles' path doesn't point to a directory or doesn't exist!\n")) {
|
||||
if (multiUser) {
|
||||
userProfilePath = profilePath;
|
||||
if (useBundledProfiles) {
|
||||
tmpPath = Glib::build_filename(argv0, "profiles");
|
||||
if(checkDirPath (tmpPath, "Error: the global's profiles' path doesn't point to a directory or doesn't exist!\n")) {
|
||||
if (userProfilePath != tmpPath)
|
||||
globalProfilePath = tmpPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
globalProfilePath = profilePath;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tmpPath = Glib::build_filename(argv0, "profiles");
|
||||
if(checkDirPath (tmpPath, "Error: the global's profiles' path doesn't point to a directory or doesn't exist!\n")) {
|
||||
globalProfilePath = tmpPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// relative paths
|
||||
if (multiUser) {
|
||||
tmpPath = Glib::build_filename(rtdir, profilePath);
|
||||
if (!checkDirPath (tmpPath, "")) {
|
||||
int retVal = safe_g_mkdir_with_parents (tmpPath, 511);
|
||||
if (!retVal)
|
||||
printf("Error: user's profiles' directory \"%s\" creation failed\n", tmpPath.c_str());
|
||||
}
|
||||
if(checkDirPath (tmpPath, "Error: the specified user's profiles' path doesn't point to a directory!\n")) {
|
||||
userProfilePath = tmpPath;
|
||||
}
|
||||
if (useBundledProfiles) {
|
||||
tmpPath = Glib::build_filename(argv0, "profiles");
|
||||
if(checkDirPath (tmpPath, "Error: the specified user's profiles' path doesn't point to a directory or doesn't exist!\n")) {
|
||||
globalProfilePath = tmpPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// common directory
|
||||
// directory name set in options is ignored, we use the default directory name
|
||||
tmpPath = Glib::build_filename(argv0, "profiles");
|
||||
if(checkDirPath (tmpPath, "Error: no global profiles' directory found!\n")) {
|
||||
globalProfilePath = tmpPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Glib::ustring Options::getPreferredProfilePath() {
|
||||
if (!userProfilePath.empty())
|
||||
return userProfilePath;
|
||||
else if (!globalProfilePath.empty())
|
||||
return globalProfilePath;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
Glib::ustring Options::findProfilePath(Glib::ustring &profName) {
|
||||
if (profName.empty())
|
||||
return "";
|
||||
|
||||
Glib::ustring p = getUserProfilePath();
|
||||
Glib::ustring fullPath = Glib::build_filename(p, profName + paramFileExtension);
|
||||
if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS))
|
||||
return p;
|
||||
|
||||
p = getGlobalProfilePath();
|
||||
fullPath = Glib::build_filename(p, profName + paramFileExtension);
|
||||
if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS))
|
||||
return p;
|
||||
else
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
void Options::setDefaults () {
|
||||
|
||||
font = "sans, 10";
|
||||
@@ -73,13 +192,14 @@ void Options::setDefaults () {
|
||||
savePathTemplate = "%p1/converted/%f";
|
||||
savePathFolder = "";
|
||||
saveUsePathTemplate = true;
|
||||
defProfRaw = "Default";
|
||||
defProfImg = "Neutral";
|
||||
defProfRaw = DEFPROFILE_RAW;
|
||||
defProfImg = DEFPROFILE_IMG;
|
||||
dateFormat = "%y-%m-%d";
|
||||
adjusterDelay = 0;
|
||||
startupDir = STARTUPDIR_LAST; // was STARTUPDIR_HOME ; an empty startupPath is now correctly handled (open in the Home dir)
|
||||
startupPath = "";
|
||||
profilePath = "profiles";
|
||||
useBundledProfiles = true;
|
||||
loadSaveProfilePath = "";
|
||||
dirBrowserWidth = 200;
|
||||
dirBrowserHeight = 150;
|
||||
@@ -373,6 +493,7 @@ if (keyFile.has_group ("Output")) {
|
||||
|
||||
if (keyFile.has_group ("Profiles")) {
|
||||
if (keyFile.has_key ("Profiles", "Directory")) profilePath = keyFile.get_string ("Profiles", "Directory");
|
||||
if (keyFile.has_key ("Profiles", "UseBundledProfiles")) useBundledProfiles = keyFile.get_boolean ("Profiles", "UseBundledProfiles");
|
||||
if (keyFile.has_key ("Profiles", "LoadSaveProfilePath")) loadSaveProfilePath = keyFile.get_string ("Profiles", "LoadSaveProfilePath");
|
||||
if (keyFile.has_key ("Profiles", "RawDefault")) defProfRaw = keyFile.get_string ("Profiles", "RawDefault");
|
||||
if (keyFile.has_key ("Profiles", "ImgDefault")) defProfImg = keyFile.get_string ("Profiles", "ImgDefault");
|
||||
@@ -627,6 +748,7 @@ int Options::saveToFile (Glib::ustring fname) {
|
||||
keyFile.set_boolean ("Output", "TunnelMetaData", tunnelMetaData);
|
||||
|
||||
keyFile.set_string ("Profiles", "Directory", profilePath);
|
||||
keyFile.set_boolean ("Profiles", "UseBundledProfiles", useBundledProfiles);
|
||||
keyFile.set_string ("Profiles", "LoadSaveProfilePath", loadSaveProfilePath);
|
||||
keyFile.set_string ("Profiles", "RawDefault", defProfRaw);
|
||||
keyFile.set_string ("Profiles", "ImgDefault", defProfImg);
|
||||
@@ -744,7 +866,9 @@ int Options::saveToFile (Glib::ustring fname) {
|
||||
}
|
||||
}
|
||||
|
||||
// User's settings directory, including images' profiles if used
|
||||
Glib::ustring Options::rtdir;
|
||||
// User's cached datas' directory
|
||||
Glib::ustring Options::cacheBaseDir;
|
||||
|
||||
void Options::load () {
|
||||
@@ -783,9 +907,6 @@ void Options::load () {
|
||||
int r = options.readFromFile (rtdir + "/options");
|
||||
// If the local option file does not exist or is broken, and the local cache folder does not exist, recreate it
|
||||
if (r && !safe_g_mkdir_with_parents (rtdir, 511)) {
|
||||
// Recreate the user's profile folder
|
||||
Glib::ustring profdir = rtdir + "/profiles";
|
||||
safe_g_mkdir_with_parents (profdir, 511);
|
||||
// Save the option file
|
||||
options.saveToFile (rtdir + "/options");
|
||||
}
|
||||
@@ -797,6 +918,38 @@ void Options::load () {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update profile's path and recreate it if necessary
|
||||
options.updatePaths();
|
||||
|
||||
// Check default Raw and Img procparams existence
|
||||
if (!options.defProfRaw.length())
|
||||
options.defProfRaw = DEFPROFILE_INTERNAL;
|
||||
else {
|
||||
Glib::ustring tmpFName = options.findProfilePath(options.defProfRaw);
|
||||
if (!tmpFName.empty()) {
|
||||
if (options.rtSettings.verbose) printf("Raws' default profile \"%s\" found\n", options.defProfRaw.c_str());
|
||||
}
|
||||
else {
|
||||
if (options.rtSettings.verbose) printf("Raws' default profile \"%s\" not found or not set -> using Internal values\n", options.defProfRaw.c_str());
|
||||
options.defProfRaw = DEFPROFILE_INTERNAL;
|
||||
options.defProfRawMissing = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.defProfImg.length())
|
||||
options.defProfImg = DEFPROFILE_INTERNAL;
|
||||
else {
|
||||
Glib::ustring tmpFName = options.findProfilePath(options.defProfImg);
|
||||
if (!tmpFName.empty()) {
|
||||
if (options.rtSettings.verbose) printf("Images' default profile \"%s\" found\n", options.defProfImg.c_str());
|
||||
}
|
||||
else {
|
||||
if (options.rtSettings.verbose) printf("Images' default profile \"%s\" not found or not set -> using Internal values\n", options.defProfImg.c_str());
|
||||
options.defProfImg = DEFPROFILE_INTERNAL;
|
||||
options.defProfImgMissing = true;
|
||||
}
|
||||
}
|
||||
|
||||
//We handle languages using a hierarchy of translations. The top of the hierarchy is default. This includes a default translation for all items
|
||||
// (most likely using simple English). The next level is the language: for instance, English, French, Chinese, etc. This file should contain a
|
||||
// generic translation for all items which differ from default. Finally there is the locale. This is region-specific items which differ from the
|
||||
|
@@ -27,6 +27,13 @@
|
||||
#define STARTUPDIR_CUSTOM 2
|
||||
#define STARTUPDIR_LAST 3
|
||||
|
||||
// Default bundled profile name to use for Raw images
|
||||
#define DEFPROFILE_RAW "Default"
|
||||
// Default bundled profile name to use for Standard images
|
||||
#define DEFPROFILE_IMG "Neutral"
|
||||
// Profile name to use for internal values' profile
|
||||
#define DEFPROFILE_INTERNAL "Internal"
|
||||
|
||||
class SaveFormat {
|
||||
|
||||
public:
|
||||
@@ -45,6 +52,13 @@ enum PPLoadLocation {PLL_Cache=0, PLL_Input=1};
|
||||
class Options {
|
||||
|
||||
private:
|
||||
bool defProfRawMissing;
|
||||
bool defProfImgMissing;
|
||||
Glib::ustring userProfilePath;
|
||||
Glib::ustring globalProfilePath;
|
||||
bool checkProfilePath(Glib::ustring &path);
|
||||
bool checkDirPath(Glib::ustring &path, Glib::ustring errString);
|
||||
void updatePaths();
|
||||
int getString (const char* src, char* dst);
|
||||
void error (int line);
|
||||
|
||||
@@ -60,7 +74,8 @@ class Options {
|
||||
int adjusterDelay;
|
||||
int startupDir;
|
||||
Glib::ustring startupPath;
|
||||
Glib::ustring profilePath;
|
||||
Glib::ustring profilePath; // can be an absolute or relative path; depending on this value, bundled profiles may not be found
|
||||
bool useBundledProfiles; // only used if multiUser == true
|
||||
Glib::ustring loadSaveProfilePath;
|
||||
Glib::ustring lastSaveAsPath;
|
||||
int saveAsDialogWidth;
|
||||
@@ -207,8 +222,15 @@ class Options {
|
||||
static void load ();
|
||||
static void save ();
|
||||
|
||||
// if multiUser=false, send back the global profile path
|
||||
Glib::ustring getPreferredProfilePath();
|
||||
Glib::ustring getUserProfilePath() { return userProfilePath; }
|
||||
Glib::ustring getGlobalProfilePath() { return globalProfilePath; }
|
||||
Glib::ustring findProfilePath(Glib::ustring &profName);
|
||||
bool has_retained_extention (Glib::ustring fname);
|
||||
bool is_extention_enabled(Glib::ustring ext);
|
||||
bool is_defProfRawMissing() { return defProfRawMissing; }
|
||||
bool is_defProfImgMissing() { return defProfImgMissing; }
|
||||
};
|
||||
|
||||
extern Options options;
|
||||
|
@@ -359,9 +359,8 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
|
||||
ffconn = flatFieldDir->signal_current_folder_changed().connect ( sigc::mem_fun(*this, &Preferences::flatFieldChanged), true);
|
||||
|
||||
std::vector<Glib::ustring> pnames;
|
||||
if (options.multiUser)
|
||||
parseDir (Options::rtdir + "/" + options.profilePath, pnames, paramFileExtension);
|
||||
parseDir (argv0 + "/" + options.profilePath, pnames, paramFileExtension);
|
||||
parseDir (options.getUserProfilePath(), pnames, paramFileExtension);
|
||||
parseDir (options.getGlobalProfilePath(), pnames, paramFileExtension);
|
||||
for (size_t i=0; i<pnames.size(); i++) {
|
||||
rprofiles->append_text (pnames[i]);
|
||||
iprofiles->append_text (pnames[i]);
|
||||
@@ -944,6 +943,9 @@ Gtk::Widget* Preferences::getSoundPanel () {
|
||||
|
||||
void Preferences::parseDir (Glib::ustring dirname, std::vector<Glib::ustring>& items, Glib::ustring ext) {
|
||||
|
||||
if (dirname.empty())
|
||||
return;
|
||||
|
||||
// process directory
|
||||
Glib::Dir* dir = NULL;
|
||||
try {
|
||||
@@ -952,9 +954,8 @@ void Preferences::parseDir (Glib::ustring dirname, std::vector<Glib::ustring>& i
|
||||
catch (const Glib::FileError& fe) {
|
||||
return;
|
||||
}
|
||||
dirname = dirname + "/";
|
||||
for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) {
|
||||
Glib::ustring fname = dirname + *i;
|
||||
Glib::ustring fname = Glib::build_filename(dirname, *i);
|
||||
Glib::ustring sname = *i;
|
||||
// ignore directories
|
||||
if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= ext.size() && sname.substr (sname.size()-ext.size(), ext.size()).casefold() == ext)
|
||||
@@ -966,7 +967,9 @@ void Preferences::parseDir (Glib::ustring dirname, std::vector<Glib::ustring>& i
|
||||
void Preferences::storePreferences () {
|
||||
|
||||
moptions.defProfRaw = rprofiles->get_active_text();
|
||||
if (moptions.defProfRaw.empty()) moptions.defProfRaw = DEFPROFILE_RAW;
|
||||
moptions.defProfImg = iprofiles->get_active_text();
|
||||
if (moptions.defProfImg.empty()) moptions.defProfImg = DEFPROFILE_IMG;
|
||||
moptions.dateFormat = dateformat->get_text();
|
||||
moptions.panAccelFactor = (int)panFactor->get_value();
|
||||
moptions.fbShowDateTime = showDateTime->get_active ();
|
||||
|
@@ -127,10 +127,8 @@ void ProfilePanel::save_clicked (GdkEventButton* event) {
|
||||
Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||
if (options.loadSaveProfilePath.length())
|
||||
dialog.set_current_folder (options.loadSaveProfilePath);
|
||||
else if (options.multiUser)
|
||||
dialog.set_current_folder (Options::rtdir + "/" + options.profilePath);
|
||||
else
|
||||
dialog.set_current_folder (argv0 + "/" + options.profilePath);
|
||||
dialog.set_current_folder (options.getPreferredProfilePath());
|
||||
|
||||
//Add response buttons the the dialog:
|
||||
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||
@@ -269,10 +267,8 @@ void ProfilePanel::load_clicked (GdkEventButton* event) {
|
||||
Gtk::FileChooserDialog dialog(M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
if (options.loadSaveProfilePath.length())
|
||||
dialog.set_current_folder (options.loadSaveProfilePath);
|
||||
else if (options.multiUser)
|
||||
dialog.set_current_folder (Options::rtdir + "/" + options.profilePath);
|
||||
else
|
||||
dialog.set_current_folder (argv0 + "/" + options.profilePath);
|
||||
dialog.set_current_folder (options.getPreferredProfilePath());
|
||||
|
||||
//Add response buttons the the dialog:
|
||||
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||
@@ -489,13 +485,19 @@ void ProfilePanel::initProfile (const Glib::ustring& profname, ProcParams* lastS
|
||||
profiles->set_active (0);
|
||||
PartialProfile* s = profileStore.getProfile (profiles->get_active_text());
|
||||
if (!s) {
|
||||
changeconn.block (false);
|
||||
s = new PartialProfile (true);
|
||||
s->set(true);
|
||||
dels = true; // we've created a temporary PartialProfile, so we set a flag to destroy it
|
||||
if (tpc)
|
||||
tpc->profileChange (s, EvPhotoLoaded, DEFPROFILE_INTERNAL);
|
||||
}
|
||||
else {
|
||||
Glib::ustring cProfile = profiles->get_active_text();
|
||||
changeconn.block (false);
|
||||
if (tpc)
|
||||
tpc->profileChange (s, EvPhotoLoaded, profiles->get_active_text());
|
||||
tpc->profileChange (s, EvPhotoLoaded, cProfile);
|
||||
}
|
||||
|
||||
if (dels) {
|
||||
s->deleteInstance();
|
||||
|
@@ -26,18 +26,58 @@ ProfileStore profileStore;
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
ProfileStore::ProfileStore () {
|
||||
storeState = STORESTATE_NOTINITIALIZED;
|
||||
parseMutex = NULL;
|
||||
}
|
||||
|
||||
bool ProfileStore::init () {
|
||||
if (storeState == STORESTATE_DELETED)
|
||||
return false;
|
||||
if (storeState == STORESTATE_NOTINITIALIZED) {
|
||||
storeState = STORESTATE_BEINGINITIALIZED;
|
||||
parseMutex = new Glib::Mutex();
|
||||
_parseProfiles ();
|
||||
storeState = STORESTATE_INITIALIZED;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ProfileStore::~ProfileStore () {
|
||||
|
||||
// This lock prevent object's suppression while scanning the directories
|
||||
storeState = STORESTATE_DELETED;
|
||||
Glib::Mutex::Lock lock(*parseMutex);
|
||||
|
||||
for (std::map<Glib::ustring,PartialProfile*>::iterator i = partProfiles.begin(); i!=partProfiles.end(); i++) {
|
||||
if (i->second->pparams) delete i->second->pparams;
|
||||
if (i->second->pedited) delete i->second->pedited;
|
||||
delete i->second;
|
||||
}
|
||||
partProfiles.clear ();
|
||||
lock.release();
|
||||
delete parseMutex;
|
||||
parseMutex = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public method to parse the profiles' directories
|
||||
* Since there's a race condition in the multithreaded environment on this object,
|
||||
* parseProfiles may need to ask for initialization of this object, and then will
|
||||
* ask a mutex lock on it, has it been initialized by this call or not
|
||||
*/
|
||||
void ProfileStore::parseProfiles () {
|
||||
|
||||
if (!init())
|
||||
// I don't even know if this situation can occur
|
||||
return;
|
||||
Glib::Mutex::Lock lock(*parseMutex);
|
||||
|
||||
_parseProfiles ();
|
||||
}
|
||||
|
||||
void ProfileStore::_parseProfiles () {
|
||||
|
||||
// clear loaded profiles
|
||||
for (std::map<Glib::ustring,PartialProfile*>::iterator i = partProfiles.begin(); i!=partProfiles.end(); i++) {
|
||||
delete i->second->pparams;
|
||||
@@ -46,28 +86,18 @@ void ProfileStore::parseProfiles () {
|
||||
}
|
||||
partProfiles.clear ();
|
||||
|
||||
if (options.multiUser) {
|
||||
Glib::ustring userPD = options.rtdir + "/" + options.profilePath;
|
||||
if (!safe_file_test (userPD, Glib::FILE_TEST_IS_DIR))
|
||||
safe_g_mkdir_with_parents (userPD, 511);
|
||||
parseDir (userPD);
|
||||
}
|
||||
parseDir (argv0 + "/" + options.profilePath);
|
||||
parseDir (options.getUserProfilePath());
|
||||
parseDir (options.getGlobalProfilePath());
|
||||
}
|
||||
|
||||
void ProfileStore::parseDir (const Glib::ustring& pdir) {
|
||||
|
||||
// reload the available profiles from the profile dir
|
||||
if (pdir!="") {
|
||||
if (pdir!="" && safe_file_test(pdir, Glib::FILE_TEST_EXISTS) && safe_file_test(pdir, Glib::FILE_TEST_IS_DIR)) {
|
||||
// process directory
|
||||
Glib::ustring dirname = pdir;
|
||||
Glib::Dir* dir = NULL;
|
||||
try {
|
||||
dir = new Glib::Dir (dirname);
|
||||
}
|
||||
catch (const Glib::FileError& fe) {
|
||||
return;
|
||||
}
|
||||
dirname = dirname + "/";
|
||||
for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) {
|
||||
Glib::ustring fname = dirname + *i;
|
||||
@@ -99,32 +129,67 @@ void ProfileStore::parseDir (const Glib::ustring& pdir) {
|
||||
}
|
||||
delete dir;
|
||||
}
|
||||
// Check if the default profiles has been found. If no, create default instance
|
||||
// This operation is safe: if the profile is finally found in another directory, the profile will be updated
|
||||
if (partProfiles.find(options.defProfRaw) == partProfiles.end()) {
|
||||
PartialProfile* pProf = new PartialProfile (true);
|
||||
pProf->set(true);
|
||||
partProfiles[options.defProfRaw] = pProf;
|
||||
}
|
||||
if (partProfiles.find(options.defProfImg) == partProfiles.end()) {
|
||||
PartialProfile* pProf = new PartialProfile (true);
|
||||
pProf->set(true);
|
||||
partProfiles[options.defProfImg] = pProf;
|
||||
}
|
||||
}
|
||||
|
||||
PartialProfile* ProfileStore::getProfile (const Glib::ustring& profname) {
|
||||
|
||||
std::map<Glib::ustring, PartialProfile*>::iterator prof = partProfiles.find(profname);
|
||||
if (prof != partProfiles.end())
|
||||
return partProfiles[profname];
|
||||
else
|
||||
if (!init())
|
||||
// I don't even know if this situation can occur
|
||||
return NULL;
|
||||
Glib::Mutex::Lock lock(*parseMutex);
|
||||
|
||||
if (partProfiles.find(profname) != partProfiles.end()) {
|
||||
return partProfiles[profname];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Glib::ustring> ProfileStore::getProfileNames () {
|
||||
|
||||
std::vector<Glib::ustring> ret;
|
||||
|
||||
if (!init())
|
||||
// I don't even know if this situation can occur
|
||||
return ret;
|
||||
Glib::Mutex::Lock lock(*parseMutex);
|
||||
|
||||
for (std::map<Glib::ustring,PartialProfile*>::iterator i = partProfiles.begin(); i!=partProfiles.end(); i++)
|
||||
ret.push_back (i->first);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send back a pointer to the default procparams for raw or standard images.
|
||||
* If the profile doesn't already exist in the profile list,
|
||||
* it will add it with default internal values, so this method never fails
|
||||
*/
|
||||
ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) {
|
||||
|
||||
if (!init())
|
||||
// I don't even know if this situation can occur
|
||||
return NULL;
|
||||
//Note: the mutex is locked in getProfile, called below
|
||||
|
||||
PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg);
|
||||
// NOTE: pProf should not be NULL anymore, since init() should have created the default profiles already, but the code is left as is
|
||||
if (!pProf) {
|
||||
Glib::ustring profName = isRaw ? options.defProfRaw : options.defProfImg;
|
||||
pProf = new PartialProfile (true);
|
||||
partProfiles[profName] = pProf;
|
||||
pProf->set(true);
|
||||
partProfiles[DEFPROFILE_INTERNAL] = pProf;
|
||||
}
|
||||
return pProf->pparams;
|
||||
}
|
||||
|
@@ -27,12 +27,24 @@
|
||||
|
||||
class ProfileStore {
|
||||
|
||||
typedef enum {
|
||||
STORESTATE_NOTINITIALIZED,
|
||||
STORESTATE_BEINGINITIALIZED,
|
||||
STORESTATE_INITIALIZED,
|
||||
STORESTATE_DELETED
|
||||
} StoreState;
|
||||
|
||||
Glib::Mutex *parseMutex;
|
||||
StoreState storeState;
|
||||
std::map<Glib::ustring, rtengine::procparams::PartialProfile*> partProfiles;
|
||||
void parseDir (const Glib::ustring& pdir);
|
||||
void _parseProfiles ();
|
||||
|
||||
public:
|
||||
|
||||
ProfileStore();
|
||||
~ProfileStore();
|
||||
bool init ();
|
||||
void parseProfiles ();
|
||||
rtengine::procparams::PartialProfile* getProfile (const Glib::ustring& profname);
|
||||
std::vector<Glib::ustring> getProfileNames ();
|
||||
|
@@ -185,10 +185,11 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
|
||||
Glib::ustring defProf = getType()==FT_Raw ? options.defProfRaw : options.defProfImg;
|
||||
|
||||
const CacheImageData* cfs=getCacheImageData();
|
||||
if (!options.customProfileBuilder.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) {
|
||||
Glib::ustring defaultPparamsPath = options.findProfilePath(defProf);
|
||||
if (!options.customProfileBuilder.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) {
|
||||
// For the filename etc. do NOT use streams, since they are not UTF8 safe
|
||||
Glib::ustring cmdLine=Glib::ustring("\"") + options.customProfileBuilder + Glib::ustring("\" \"") + fname + Glib::ustring("\" \"")
|
||||
+ options.rtdir + Glib::ustring("/") + options.profilePath + Glib::ustring("/") + defProf + Glib::ustring(".pp3") + Glib::ustring("\" ");
|
||||
+ Glib::build_filename(defaultPparamsPath, defProf + paramFileExtension) + Glib::ustring("\" ");
|
||||
|
||||
// ustring doesn't know int etc formatting, so take these via (unsafe) stream
|
||||
std::ostringstream strm;
|
||||
|
Reference in New Issue
Block a user