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:
natureh
2012-05-25 10:42:56 +02:00
parent e5d42eb5eb
commit 6ae731e84a
17 changed files with 386 additions and 61 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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 ();

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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 ();

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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 ();

View File

@@ -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;