From f78cadf4d1f89965aa1a71b86bb783c66fe9e4e4 Mon Sep 17 00:00:00 2001 From: natureh Date: Sat, 2 Jun 2012 14:48:35 +0200 Subject: [PATCH] Solving issue 872: "RT file-open/save windows should remember last used dir", on behalf of Johannes Wienke --- rtgui/curveeditorgroup.cc | 24 +- rtgui/curveeditorgroup.h | 21 +- rtgui/darkframe.cc | 7 +- rtgui/darkframe.h | 2 + rtgui/diagonalcurveeditorsubgroup.cc | 2 +- rtgui/diagonalcurveeditorsubgroup.h | 2 +- rtgui/filebrowser.cc | 10 +- rtgui/flatcurveeditorsubgroup.cc | 2 +- rtgui/flatcurveeditorsubgroup.h | 2 +- rtgui/flatfield.cc | 7 +- rtgui/flatfield.h | 2 + rtgui/guiutils.cc | 29 + rtgui/guiutils.h | 34 + rtgui/hsvequalizer.cc | 2 +- rtgui/icmpanel.cc | 17 +- rtgui/icmpanel.h | 4 +- rtgui/labcurve.cc | 2 +- rtgui/main.cc | 2 +- rtgui/options.cc | 90 ++- rtgui/options.h | 513 ++++++------- rtgui/profilepanel.cc | 1012 +++++++++++++------------- rtgui/rgbcurves.cc | 2 +- rtgui/tonecurve.cc | 2 +- 23 files changed, 973 insertions(+), 817 deletions(-) diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index d321f1130..8ffc6441d 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -29,7 +29,7 @@ extern Glib::ustring argv0; -CurveEditorGroup::CurveEditorGroup (Glib::ustring groupLabel) : cl(NULL), cp(NULL) { +CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), cl(NULL), cp(NULL) { curveEditors.clear(); displayedCurve = 0; numberOfPackedCurve = 0; @@ -64,12 +64,12 @@ CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabe switch (cType) { case (CT_Diagonal): if (!diagonalSubGroup) { - diagonalSubGroup = new DiagonalCurveEditorSubGroup(this); + diagonalSubGroup = new DiagonalCurveEditorSubGroup(this, curveDir); } return (static_cast(diagonalSubGroup->addCurve(curveLabel))); case (CT_Flat): if (!flatSubGroup) { - flatSubGroup = new FlatCurveEditorSubGroup(this); + flatSubGroup = new FlatCurveEditorSubGroup(this, curveDir); } return (static_cast(flatSubGroup->addCurve(curveLabel, periodic))); default: @@ -294,16 +294,17 @@ void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) { } } +CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : + curveDir(curveDir) { +} + Glib::ustring CurveEditorSubGroup::outputFile () { Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); -// if (options.multiUser) -// dialog.set_current_folder (Options::rtdir + "/" + options.profilePath); -// else -// dialog.set_current_folder (argv0 + "/" + options.profilePath); + FileChooserLastFolderPersister persister(&dialog, curveDir); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_APPLY); Gtk::FileFilter filter_pp; filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE")); @@ -323,7 +324,7 @@ Glib::ustring CurveEditorSubGroup::outputFile () { fname = dialog.get_filename(); - if (result==Gtk::RESPONSE_OK) { + if (result==Gtk::RESPONSE_APPLY) { if (getExtension (fname)!="rtc") fname = fname + ".rtc"; @@ -350,9 +351,10 @@ Glib::ustring CurveEditorSubGroup::outputFile () { Glib::ustring CurveEditorSubGroup::inputFile () { Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); + FileChooserLastFolderPersister persister(&dialog, curveDir); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_OK); + dialog.add_button(Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); Gtk::FileFilter filter_pp; filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE")); @@ -367,7 +369,7 @@ Glib::ustring CurveEditorSubGroup::inputFile () { int result = dialog.run(); Glib::ustring fname; - if (result==Gtk::RESPONSE_OK) { + if (result==Gtk::RESPONSE_APPLY) { fname = dialog.get_filename(); if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) return fname; diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index b2f24cf5a..27c5268df 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -46,6 +46,9 @@ class CurveEditorGroup : public Gtk::VBox, public CurveListener { friend class DiagonalCurveEditorSubGroup; friend class FlatCurveEditorSubGroup; +private: + Glib::ustring& curveDir; + protected: Gtk::Label* curveGroupLabel; Gtk::Button* curve_reset; @@ -60,7 +63,12 @@ protected: unsigned int numberOfPackedCurve; public: - CurveEditorGroup(Glib::ustring groupLabel = ""); + /** + * @param curveDir The folder used by load and save dialogs for the curve. + * This variable will be updated with actions in the + * dialogs. + */ + CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); ~CurveEditorGroup(); void newLine(); void curveListComplete(); @@ -88,6 +96,9 @@ class CurveEditorSubGroup { friend class CurveEditorGroup; +private: + Glib::ustring& curveDir; + protected: int valLinear; int valUnchanged; @@ -100,6 +111,14 @@ public: virtual void setColorProvider (ColorProvider* p) = 0; protected: + + /** + * @param curveDir The folder used by load and save dialogs for the curve. + * This variable will be updated with actions in the + * dialogs. + */ + CurveEditorSubGroup(Glib::ustring& curveDir); + Glib::ustring outputFile (); Glib::ustring inputFile (); diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index 3e3c85096..193bc1c80 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -30,6 +30,7 @@ DarkFrame::DarkFrame () : Gtk::VBox(), FoldableToolPanel(this) { hbdf = Gtk::manage(new Gtk::HBox()); darkFrameFile = Gtk::manage(new MyFileChooserButton(M("TP_DARKFRAME_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); + darkFrameFilePersister.reset(new FileChooserLastFolderPersister(darkFrameFile, options.lastDarkframeDir)); dfLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); btnReset = Gtk::manage(new Gtk::Button()); btnReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); @@ -59,8 +60,6 @@ void DarkFrame::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi } if (safe_file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) darkFrameFile->set_filename (pp->raw.dark_frame); - else if( !options.rtSettings.darkFramesPath.empty() ) - darkFrameFile->set_current_folder( options.rtSettings.darkFramesPath ); hbdf->set_sensitive( !pp->raw.df_autoselect ); lastDFauto = pp->raw.df_autoselect; @@ -139,8 +138,8 @@ void DarkFrame::darkFrameReset() //darkFrameFile->set_current_name(""); darkFrameFile->set_filename (""); - if( !options.rtSettings.darkFramesPath.empty() ) - darkFrameFile->set_current_folder( options.rtSettings.darkFramesPath ); + if (!options.lastDarkframeDir.empty()) + darkFrameFile->set_current_folder(options.lastDarkframeDir); dfInfo->set_text(""); if (listener) diff --git a/rtgui/darkframe.h b/rtgui/darkframe.h index 755f15e7c..91e405a26 100644 --- a/rtgui/darkframe.h +++ b/rtgui/darkframe.h @@ -19,6 +19,7 @@ #ifndef _DARKFRAME_H_ #define _DARKFRAME_H_ +#include #include #include "toolpanel.h" #include "../rtengine/rawimage.h" @@ -35,6 +36,7 @@ class DarkFrame : public Gtk::VBox, public FoldableToolPanel { protected: MyFileChooserButton *darkFrameFile; + std::auto_ptr darkFrameFilePersister; Gtk::HBox *hbdf; Gtk::Button *btnReset; Gtk::Label *dfLabel; diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index 92238fbed..515e89508 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -31,7 +31,7 @@ #include "curveeditor.h" #include "diagonalcurveeditorsubgroup.h" -DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt) { +DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) { valLinear = (int)DCT_Linear; valUnchanged = (int)DCT_Unchanged; diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h index 05ffb6c38..fc5fb5a80 100644 --- a/rtgui/diagonalcurveeditorsubgroup.h +++ b/rtgui/diagonalcurveeditorsubgroup.h @@ -59,7 +59,7 @@ protected: int activeParamControl; public: - DiagonalCurveEditorSubGroup(CurveEditorGroup* prt); + DiagonalCurveEditorSubGroup(CurveEditorGroup* prt, Glib::ustring& curveDir); virtual ~DiagonalCurveEditorSubGroup(); DiagonalCurveEditor* addCurve(Glib::ustring curveLabel = ""); diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index cc9c22f98..1f1122431 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -598,11 +598,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) { if( !mselected.empty() ){ rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams(); Gtk::FileChooserDialog fc("Dark Frame",Gtk::FILE_CHOOSER_ACTION_OPEN ); + FileChooserLastFolderPersister persister(&fc, options.lastDarkframeDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); - if( pp.raw.dark_frame.empty()) - fc.set_current_folder( options.rtSettings.darkFramesPath ); - else + if(!pp.raw.dark_frame.empty()) fc.set_filename( pp.raw.dark_frame ); if( fc.run() == Gtk::RESPONSE_APPLY ){ for (size_t i=0; ithumbnail->getProcParams(); Gtk::FileChooserDialog fc("Flat Field",Gtk::FILE_CHOOSER_ACTION_OPEN ); + FileChooserLastFolderPersister persister(&fc, options.lastFlatfieldDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); - if( pp.raw.ff_file.empty()) - fc.set_current_folder( options.rtSettings.flatFieldsPath ); - else + if(!pp.raw.ff_file.empty()) fc.set_filename( pp.raw.ff_file ); if( fc.run() == Gtk::RESPONSE_APPLY ){ for (size_t i=0; iset_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); @@ -80,8 +81,6 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi } if (safe_file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) flatFieldFile->set_filename (pp->raw.ff_file); - else if( !options.rtSettings.flatFieldsPath.empty() ) - flatFieldFile->set_current_folder( options.rtSettings.flatFieldsPath ); hbff->set_sensitive( !pp->raw.ff_AutoSelect ); lastFFAutoSelect = pp->raw.ff_AutoSelect; @@ -176,8 +175,8 @@ void FlatField::flatFieldFile_Reset() //flatFieldFile->set_current_name(""); flatFieldFile->set_filename (""); - if( !options.rtSettings.flatFieldsPath.empty() ) - flatFieldFile->set_current_folder( options.rtSettings.flatFieldsPath ); + if (!options.lastFlatfieldDir.empty()) + flatFieldFile->set_current_folder(options.lastFlatfieldDir); ffInfo->set_text(""); if (listener) diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 148b6cad8..de2f87823 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -19,6 +19,7 @@ #ifndef _FLATFIELD_H_ #define _FLATFIELD_H_ +#include #include #include "adjuster.h" #include "toolpanel.h" @@ -36,6 +37,7 @@ class FlatField : public Gtk::VBox, public AdjusterListener, public FoldableTool protected: MyFileChooserButton *flatFieldFile; + std::auto_ptr flatFieldFilePersister; Gtk::Label *ffLabel; Gtk::Label *ffInfo; Gtk::Button *flatFieldFileReset; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 35555ff4f..a20412f02 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -22,6 +22,8 @@ #include "../rtengine/utils.h" #include "rtimage.h" +#include + using namespace std; bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference) { @@ -402,6 +404,33 @@ bool MyFileChooserButton::on_scroll_event (GdkEventScroll* event) { return false; } +FileChooserLastFolderPersister::FileChooserLastFolderPersister( + Gtk::FileChooser* chooser, Glib::ustring& folderVariable) : + chooser(chooser), folderVariable(folderVariable) { + assert(chooser != NULL); + + selectionChangedConnetion = chooser->signal_selection_changed().connect( + sigc::mem_fun(*this, + &FileChooserLastFolderPersister::selectionChanged)); + + if (!folderVariable.empty()) { + chooser->set_current_folder(folderVariable); + } + +} + +FileChooserLastFolderPersister::~FileChooserLastFolderPersister() { + +} + +void FileChooserLastFolderPersister::selectionChanged() { + + if (!chooser->get_current_folder().empty()) { + folderVariable = chooser->get_current_folder(); + } + +} + TextOrIcon::TextOrIcon (Glib::ustring fname, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type) { imgIcon = 0; diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index d531822dc..a46011276 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -138,6 +138,40 @@ public: MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN); }; +/** + * A class which maintains the last folder for a FileChooserDialog or Button by + * caching it in a a variable (which can be persisted externally). + * Each time the user selects a file or folder, the provided variable is updated + * with the associated folder. The path found in the variable is set in the + * dialog instance at constructions time of this object. + */ +class FileChooserLastFolderPersister: public Glib::Object { +public: + + /** + * Installs this persister on the provided GtkFileChooser instance and + * applies the current folder found in @p folderVariable for the dialog. + * + * @param chooser file chooser to maintain + * @param folderVariable variable storage to use for this dialog + */ + FileChooserLastFolderPersister(Gtk::FileChooser* chooser, Glib::ustring& folderVariable); + + virtual ~FileChooserLastFolderPersister(); + +private: + + /** + * Signal handler for the GtkFileChooser selection action. + */ + void selectionChanged(); + + Gtk::FileChooser* chooser; + Glib::ustring& folderVariable; + sigc::connection selectionChangedConnetion; + +}; + enum TOITypes { TOI_TEXT, TOI_ICON diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc index 7ea4b62d7..e2dbea66d 100644 --- a/rtgui/hsvequalizer.cc +++ b/rtgui/hsvequalizer.cc @@ -27,7 +27,7 @@ using namespace rtengine::procparams; HSVEqualizer::HSVEqualizer () : Gtk::VBox(), FoldableToolPanel(this) { - curveEditorG = new CurveEditorGroup (M("TP_HSVEQUALIZER_CHANNEL")); + curveEditorG = new CurveEditorGroup (options.lastHsvCurvesDir, M("TP_HSVEQUALIZER_CHANNEL")); curveEditorG->setCurveListener (this); curveEditorG->setColorProvider (this); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 1c3699d4b..dc77bc980 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -30,14 +30,13 @@ using namespace rtengine::procparams; extern Options options; -Glib::ustring ICMPanel::lastICCWorkDir; - ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), icmplistener(NULL) { // set_border_width (4); ipDialog = Gtk::manage (new MyFileChooserButton (M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); ipDialog->set_tooltip_text (M("TP_ICM_INPUTCUSTOM_TOOLTIP")); + ipDialogPersister.reset(new FileChooserLastFolderPersister(ipDialog, options.lastIccDir)); Gtk::Label* ilab = Gtk::manage (new Gtk::Label ()); ilab->set_alignment (0.0, 0.5); @@ -188,8 +187,6 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), ipDialog->add_filter (filter_icc); ipDialog->add_filter (filter_any); - ipDialog->set_current_folder ( lastICCWorkDir.empty() ? options.rtSettings.iccDirectory : lastICCWorkDir); - oldip = ""; wnames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::wpChanged) ); @@ -309,9 +306,6 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) { pp->icm.input = ""; // just a directory Glib::ustring p=Glib::path_get_dirname(ipDialog->get_filename ()); - if (p!=options.rtSettings.iccDirectory) { - lastICCWorkDir=p; - } } pp->icm.working = wnames->get_active_text (); @@ -476,12 +470,12 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) { enableListener (); } -void ICMPanel::ipSelectionChanged () { +void ICMPanel::ipSelectionChanged() { - if (ipDialog->get_filename () == "") - return; + if (ipDialog->get_filename() == "") + return; - ipChanged (); + ipChanged(); } void ICMPanel::saveReferencePressed () { @@ -489,6 +483,7 @@ void ICMPanel::saveReferencePressed () { if (!icmplistener) return; Gtk::FileChooserDialog dialog(M("TP_ICM_SAVEREFERENCEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); + FileChooserLastFolderPersister persister(&dialog, options.lastProfilingReferenceDir); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 0b8c71916..4b3fc33a8 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -19,6 +19,8 @@ #ifndef _ICMPANEL_ #define _ICMPANEL_ +#include + #include #include "adjuster.h" #include "guiutils.h" @@ -58,13 +60,13 @@ class ICMPanel : public Gtk::VBox, public AdjusterListener, public FoldableToolP Gtk::RadioButton* ofromfile; Gtk::RadioButton* iunchanged; MyFileChooserButton* ipDialog; + std::auto_ptr ipDialogPersister; Gtk::RadioButton::Group opts; Gtk::Button* saveRef; sigc::connection ipc; Glib::ustring oldip; ICMPanelListener* icmplistener; - static Glib::ustring lastICCWorkDir; bool enableLastICCWorkDirChange; public: diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index ddcecf881..fb6c62ec8 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -67,7 +67,7 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this) { hsep3->show (); pack_start (*hsep3); - curveEditorG = new CurveEditorGroup (); + curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); curveEditorG->setCurveListener (this); curveEditorG->setColorProvider (this); diff --git a/rtgui/main.cc b/rtgui/main.cc index d65567df7..33fe7375a 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -339,7 +339,7 @@ int processLineParams( int argc, char **argv ) } else { options.saveUsePathTemplate = true; - if (!options.savePathTemplate.length()) + if (options.savePathTemplate.empty()) // If the save path template is empty, we use its default value options.savePathTemplate = "%p1/converted/%f"; } diff --git a/rtgui/options.cc b/rtgui/options.cc index e5a791b1e..ae8d51515 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -36,6 +36,9 @@ #include #endif +Glib::ustring Options::rtdir; +Glib::ustring Options::cacheBaseDir; + Options options; Glib::ustring versionString = VERSION; Glib::ustring paramFileExtension = ".pp3"; @@ -135,17 +138,30 @@ void Options::updatePaths() { if(checkDirPath (tmpPath, "Error: no global profiles' directory found!\n")) { globalProfilePath = tmpPath; } - } + } } + + Glib::ustring preferredPath = getPreferredProfilePath(); + // Paths are updated only if the user or global profile path is set + if (lastRgbCurvesDir.empty() || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_IS_DIR)) + lastRgbCurvesDir = preferredPath; + if (lastLabCurvesDir.empty() || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) + lastLabCurvesDir = preferredPath; + if (lastHsvCurvesDir.empty() || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR)) + lastHsvCurvesDir = preferredPath; + if (lastToneCurvesDir.empty() || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_IS_DIR)) + lastToneCurvesDir = preferredPath; + if (lastProfilingReferenceDir.empty() || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_IS_DIR)) + lastProfilingReferenceDir = preferredPath; } Glib::ustring Options::getPreferredProfilePath() { - if (!userProfilePath.empty()) - return userProfilePath; - else if (!globalProfilePath.empty()) - return globalProfilePath; - else - return ""; + if (!userProfilePath.empty()) + return userProfilePath; + else if (!globalProfilePath.empty()) + return globalProfilePath; + else + return ""; } Glib::ustring Options::findProfilePath(Glib::ustring &profName) { @@ -198,9 +214,7 @@ void Options::setDefaults () { 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; preferencesWidth = 0; @@ -219,6 +233,8 @@ void Options::setDefaults () { fbShowHidden = false; fbArrangement = 2; // was 0 multiUser = true; + profilePath = "profiles"; + loadSaveProfilePath = ""; // will be corrected in load as otherwise construction fails version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize thumbSize = 240; // was 80 thumbSizeTab = 80; @@ -401,6 +417,21 @@ void Options::setDefaults () { rtSettings.best = "BestRGB"; rtSettings.verbose = false; rtSettings.gamutICC = true; + + lastIccDir = rtSettings.iccDirectory; + lastDarkframeDir = rtSettings.darkFramesPath; + lastFlatfieldDir = rtSettings.flatFieldsPath; + + // There is no reasonable default for curves. We can still suppose that they will take place + // in a subdirectory of the user's own ProcParams presets, i.e. in a subdirectory + // of the one pointed to by the "profile" field. + // The following fields will then be initialized when "profile" will have its final value, + // at the end of the "updatePaths" method. + lastRgbCurvesDir = ""; + lastLabCurvesDir = ""; + lastHsvCurvesDir = ""; + lastToneCurvesDir = ""; + lastProfilingReferenceDir = ""; } Options* Options::copyFrom (Options* other) { @@ -647,11 +678,33 @@ if (keyFile.has_group ("Fast Export")) { if (keyFile.has_key ("Fast Export", "fastexport_resize_width" )) fastexport_resize_width = keyFile.get_integer ("Fast Export", "fastexport_resize_width" ); if (keyFile.has_key ("Fast Export", "fastexport_resize_height" )) fastexport_resize_height = keyFile.get_integer ("Fast Export", "fastexport_resize_height" ); } + +if (keyFile.has_group ("Dialogs")) { + safeDirGet(keyFile, "Dialogs", "LastIccDir", lastIccDir); + safeDirGet(keyFile, "Dialogs", "LastDarkframeDir", lastDarkframeDir); + safeDirGet(keyFile, "Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + safeDirGet(keyFile, "Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastLabCurvesDir", lastLabCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastToneCurvesDir", lastToneCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); +} + filterOutParsedExtensions (); return 0; } +bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, + const Glib::ustring& entryName, Glib::ustring& destination) +{ + if (keyFile.has_key(section, entryName) && !keyFile.get_string(section, entryName).empty()) { + destination = keyFile.get_string(section, entryName); + return true; + } + return false; +} + int Options::saveToFile (Glib::ustring fname) { rtengine::SafeKeyFile keyFile; @@ -855,6 +908,14 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_integer ("Fast Export", "fastexport_resize_width" , fastexport_resize_width ); keyFile.set_integer ("Fast Export", "fastexport_resize_height" , fastexport_resize_height ); + keyFile.set_string ("Dialogs", "LastIccDir", lastIccDir); + keyFile.set_string ("Dialogs", "LastDarkframeDir", lastDarkframeDir); + keyFile.set_string ("Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + keyFile.set_string ("Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); + keyFile.set_string ("Dialogs", "LastLabCurvesDir", lastLabCurvesDir); + keyFile.set_string ("Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); + keyFile.set_string ("Dialogs", "LastToneCurvesDir", lastToneCurvesDir); + keyFile.set_string ("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); FILE *f = safe_g_fopen (fname, "wt"); if (f==NULL) @@ -866,11 +927,6 @@ 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 () { // Find the application data path @@ -922,7 +978,7 @@ void Options::load () { options.updatePaths(); // Check default Raw and Img procparams existence - if (!options.defProfRaw.length()) + if (options.defProfRaw.empty()) options.defProfRaw = DEFPROFILE_INTERNAL; else { Glib::ustring tmpFName = options.findProfilePath(options.defProfRaw); @@ -936,7 +992,7 @@ void Options::load () { } } - if (!options.defProfImg.length()) + if (options.defProfImg.empty()) options.defProfImg = DEFPROFILE_INTERNAL; else { Glib::ustring tmpFName = options.findProfilePath(options.defProfImg); @@ -1003,7 +1059,7 @@ bool Options::has_retained_extention (Glib::ustring fname) { Glib::ustring ext = getExtension(fname).lowercase(); - if (ext.length()) { + if (!ext.empty()) { // there is an extension to the filename // look out if it has one of the retained extensions diff --git a/rtgui/options.h b/rtgui/options.h index c8b7a6831..3eba1a8f1 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -1,243 +1,270 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * 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 . - */ -#ifndef _OPTIONS_ -#define _OPTIONS_ - -#include -#include "../rtengine/rtengine.h" - -#define STARTUPDIR_CURRENT 0 -#define STARTUPDIR_HOME 1 -#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: - Glib::ustring format; - int pngBits; - int pngCompression; - int jpegQuality; - int tiffBits; - bool tiffUncompressed; - bool saveParams; -}; - -enum ThFileType {FT_Invalid=-1, FT_None=0, FT_Raw=1, FT_Jpeg=2, FT_Tiff=3, FT_Png=4, FT_Custom=5, FT_Tiff16=6, FT_Png16=7, FT_Custom16=8}; -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); - - public: - bool savesParamsAtExit; - SaveFormat saveFormat,saveFormatBatch; - Glib::ustring savePathTemplate; - Glib::ustring savePathFolder; - bool saveUsePathTemplate; - Glib::ustring defProfRaw; - Glib::ustring defProfImg; - Glib::ustring dateFormat; - int adjusterDelay; - int startupDir; - Glib::ustring startupPath; - 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; - int saveAsDialogHeight; - int toolPanelWidth; - int browserToolPanelWidth; - int browserToolPanelHeight; - int historyPanelWidth; - Glib::ustring font; - int windowWidth; - int windowHeight; - bool windowMaximized; - int dirBrowserWidth; - int dirBrowserHeight; - int preferencesWidth; - int preferencesHeight; - int lastScale; - int panAccelFactor; - int lastCropSize; - bool fbOnlyRaw; - bool fbShowDateTime; - bool fbShowBasicExif; - bool fbShowExpComp; - bool fbShowHidden; - int fbArrangement; - bool multiUser; - static Glib::ustring rtdir; - Glib::ustring version; - int thumbSize,thumbSizeTab; - bool showHistory; - int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden - bool showInfo; - bool mainNBVertical; // main notebook vertical tabs? - int cropPPI; - bool showClippedHighlights; - bool showClippedShadows; - int highlightThreshold; - int shadowThreshold; - bool blinkClipped; - int bgcolor; - Glib::ustring language; - bool languageAutoDetect; - Glib::ustring theme; - bool slimUI; - bool useSystemTheme; - static Glib::ustring cacheBaseDir; - bool autoSuffix; - bool saveParamsFile; - bool saveParamsCache; - PPLoadLocation paramsLoadLocation; - bool procQueueEnabled; - Glib::ustring gimpDir; - Glib::ustring psDir; - Glib::ustring customEditorProg; - Glib::ustring customProfileBuilder; - int editorToSendTo; - int maxThumbnailHeight; - std::size_t maxCacheEntries; - ThFileType thumbnailFormat; - int thumbInterp; // 0: nearest, 1: bilinear - bool liveThumbnails; - std::vector parseExtensions; // List containing all extensions type - std::vector parseExtensionsEnabled; // List of bool to retain extension or not - std::vector parsedExtensions; // List containing all retained extensions (lowercase) - std::vector tpOpen; - //std::vector crvOpen; - std::vector baBehav; - rtengine::Settings rtSettings; - - std::vector favoriteDirs; - std::vector renameTemplates; - bool renameUseTemplates; - bool internalThumbIfUntouched; - bool overwriteOutputFile; - - std::vector thumbnailZoomRatios; - bool overlayedFileNames; - bool showFileNames; - bool tabbedUI; - int previewSizeTab,previewSizeBrowser; - int multiDisplayMode; // 0=none, 1=Edit panels on other display - std::vector cutOverlayBrush; // Red;Green;Blue;Alpha , all ranging 0..1 - - Glib::ustring sndBatchQueueDone; - Glib::ustring sndLngEditProcDone; - double sndLngEditProcDoneSecs; // Minimum processing time seconds till the sound is played - bool sndEnable; - - bool tunnelMetaData; // Pass through IPTC and XMP unchanged - int histogramPosition; // 0=disabled, 1=left pane, 2=right pane - bool histogramBar; - bool showProfileSelector; - bool squareDetailWindow; - bool FileBrowserToolbarSingleRow; - bool hideTPVScrollbar; - bool UseIconNoText; - int whiteBalanceSpotSize; - - bool menuGroupRank; - bool menuGroupLabel; - bool menuGroupFileOperations; - bool menuGroupProfileOperations; - bool menuGroupExtProg; - - // fast export options - bool fastexport_bypass_sharpening; - bool fastexport_bypass_sharpenEdge; - bool fastexport_bypass_sharpenMicro; - //bool fastexport_bypass_lumaDenoise; - //bool fastexport_bypass_colorDenoise; - bool fastexport_bypass_defringe; - bool fastexport_bypass_dirpyrDenoise; - bool fastexport_bypass_sh_hq; - bool fastexport_bypass_dirpyrequalizer; - bool fastexport_bypass_raw_all_enhance; - bool fastexport_bypass_raw_ccSteps; - bool fastexport_bypass_raw_dcb_iterations; - bool fastexport_bypass_raw_dcb_enhance; - bool fastexport_bypass_raw_ca; - bool fastexport_bypass_raw_linenoise; - bool fastexport_bypass_raw_greenthresh; - bool fastexport_bypass_raw_df; - bool fastexport_bypass_raw_ff; - Glib::ustring fastexport_raw_dmethod; - Glib::ustring fastexport_icm_input; - Glib::ustring fastexport_icm_working; - Glib::ustring fastexport_icm_output; - Glib::ustring fastexport_icm_gamma; - bool fastexport_resize_enabled; - double fastexport_resize_scale; - Glib::ustring fastexport_resize_appliesTo; - Glib::ustring fastexport_resize_method; - int fastexport_resize_dataspec; - int fastexport_resize_width; - int fastexport_resize_height; - - Options (); - - Options* copyFrom (Options* other); - void filterOutParsedExtensions (); - void setDefaults (); - int readFromFile (Glib::ustring fname); - int saveToFile (Glib::ustring fname); - 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; -extern Glib::ustring argv0; -extern Glib::ustring argv1; -extern bool simpleEditor; -extern Glib::ustring versionString; -extern Glib::ustring paramFileExtension; - -#endif +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * 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 . + */ +#ifndef _OPTIONS_ +#define _OPTIONS_ + +#include +#include "../rtengine/rtengine.h" + +#define STARTUPDIR_CURRENT 0 +#define STARTUPDIR_HOME 1 +#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: + Glib::ustring format; + int pngBits; + int pngCompression; + int jpegQuality; + int tiffBits; + bool tiffUncompressed; + bool saveParams; +}; + +enum ThFileType {FT_Invalid=-1, FT_None=0, FT_Raw=1, FT_Jpeg=2, FT_Tiff=3, FT_Png=4, FT_Custom=5, FT_Tiff16=6, FT_Png16=7, FT_Custom16=8}; +enum PPLoadLocation {PLL_Cache=0, PLL_Input=1}; + +namespace rtengine { + class SafeKeyFile; +} + +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); + /** + * Safely reads a directory from the configuration file and only applies it + * to the provided destination variable if there is a non-empty string in + * the configuration. + * + * @param keyFile file to read configuration from + * @param section name of the section in the configuration file + * @param entryName name of the entry in the configuration file + * @param destination destination variable to store to + * @return @c true if @p destination was changed + */ + bool safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, + const Glib::ustring& entryName, Glib::ustring& destination); + + public: + bool savesParamsAtExit; + SaveFormat saveFormat,saveFormatBatch; + Glib::ustring savePathTemplate; + Glib::ustring savePathFolder; + bool saveUsePathTemplate; + Glib::ustring defProfRaw; + Glib::ustring defProfImg; + Glib::ustring dateFormat; + int adjusterDelay; + int startupDir; + Glib::ustring startupPath; + 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; + int saveAsDialogHeight; + int toolPanelWidth; + int browserToolPanelWidth; + int browserToolPanelHeight; + int historyPanelWidth; + Glib::ustring font; + int windowWidth; + int windowHeight; + bool windowMaximized; + int dirBrowserWidth; + int dirBrowserHeight; + int preferencesWidth; + int preferencesHeight; + int lastScale; + int panAccelFactor; + int lastCropSize; + bool fbOnlyRaw; + bool fbShowDateTime; + bool fbShowBasicExif; + bool fbShowExpComp; + bool fbShowHidden; + int fbArrangement; + bool multiUser; + static Glib::ustring rtdir; + Glib::ustring version; + int thumbSize,thumbSizeTab; + bool showHistory; + int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden + bool showInfo; + bool mainNBVertical; // main notebook vertical tabs? + int cropPPI; + bool showClippedHighlights; + bool showClippedShadows; + int highlightThreshold; + int shadowThreshold; + bool blinkClipped; + int bgcolor; + Glib::ustring language; + bool languageAutoDetect; + Glib::ustring theme; + bool slimUI; + bool useSystemTheme; + static Glib::ustring cacheBaseDir; + bool autoSuffix; + bool saveParamsFile; + bool saveParamsCache; + PPLoadLocation paramsLoadLocation; + bool procQueueEnabled; + Glib::ustring gimpDir; + Glib::ustring psDir; + Glib::ustring customEditorProg; + Glib::ustring customProfileBuilder; + int editorToSendTo; + int maxThumbnailHeight; + std::size_t maxCacheEntries; + ThFileType thumbnailFormat; + int thumbInterp; // 0: nearest, 1: bilinear + bool liveThumbnails; + std::vector parseExtensions; // List containing all extensions type + std::vector parseExtensionsEnabled; // List of bool to retain extension or not + std::vector parsedExtensions; // List containing all retained extensions (lowercase) + std::vector tpOpen; + //std::vector crvOpen; + std::vector baBehav; + rtengine::Settings rtSettings; + + std::vector favoriteDirs; + std::vector renameTemplates; + bool renameUseTemplates; + bool internalThumbIfUntouched; + bool overwriteOutputFile; + + std::vector thumbnailZoomRatios; + bool overlayedFileNames; + bool showFileNames; + bool tabbedUI; + int previewSizeTab,previewSizeBrowser; + int multiDisplayMode; // 0=none, 1=Edit panels on other display + std::vector cutOverlayBrush; // Red;Green;Blue;Alpha , all ranging 0..1 + + Glib::ustring sndBatchQueueDone; + Glib::ustring sndLngEditProcDone; + double sndLngEditProcDoneSecs; // Minimum processing time seconds till the sound is played + bool sndEnable; + + bool tunnelMetaData; // Pass through IPTC and XMP unchanged + int histogramPosition; // 0=disabled, 1=left pane, 2=right pane + bool histogramBar; + bool showProfileSelector; + bool squareDetailWindow; + bool FileBrowserToolbarSingleRow; + bool hideTPVScrollbar; + bool UseIconNoText; + int whiteBalanceSpotSize; + + bool menuGroupRank; + bool menuGroupLabel; + bool menuGroupFileOperations; + bool menuGroupProfileOperations; + bool menuGroupExtProg; + + // fast export options + bool fastexport_bypass_sharpening; + bool fastexport_bypass_sharpenEdge; + bool fastexport_bypass_sharpenMicro; + //bool fastexport_bypass_lumaDenoise; + //bool fastexport_bypass_colorDenoise; + bool fastexport_bypass_defringe; + bool fastexport_bypass_dirpyrDenoise; + bool fastexport_bypass_sh_hq; + bool fastexport_bypass_dirpyrequalizer; + bool fastexport_bypass_raw_all_enhance; + bool fastexport_bypass_raw_ccSteps; + bool fastexport_bypass_raw_dcb_iterations; + bool fastexport_bypass_raw_dcb_enhance; + bool fastexport_bypass_raw_ca; + bool fastexport_bypass_raw_linenoise; + bool fastexport_bypass_raw_greenthresh; + bool fastexport_bypass_raw_df; + bool fastexport_bypass_raw_ff; + Glib::ustring fastexport_raw_dmethod; + Glib::ustring fastexport_icm_input; + Glib::ustring fastexport_icm_working; + Glib::ustring fastexport_icm_output; + Glib::ustring fastexport_icm_gamma; + bool fastexport_resize_enabled; + double fastexport_resize_scale; + Glib::ustring fastexport_resize_appliesTo; + Glib::ustring fastexport_resize_method; + int fastexport_resize_dataspec; + int fastexport_resize_width; + int fastexport_resize_height; + + // Dialog settings + Glib::ustring lastIccDir; + Glib::ustring lastDarkframeDir; + Glib::ustring lastFlatfieldDir; + Glib::ustring lastRgbCurvesDir; + Glib::ustring lastLabCurvesDir; + Glib::ustring lastHsvCurvesDir; + Glib::ustring lastToneCurvesDir; + Glib::ustring lastProfilingReferenceDir; + + Options (); + + Options* copyFrom (Options* other); + void filterOutParsedExtensions (); + void setDefaults (); + int readFromFile (Glib::ustring fname); + int saveToFile (Glib::ustring fname); + 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; +extern Glib::ustring argv0; +extern Glib::ustring argv1; +extern bool simpleEditor; +extern Glib::ustring versionString; +extern Glib::ustring paramFileExtension; + +#endif diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index 7b8189e61..dab76bc8c 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -1,510 +1,502 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include "profilepanel.h" -#include "options.h" -#include "profilestore.h" -#include "clipboard.h" -#include "multilangmgr.h" -#include "../rtengine/safegtk.h" -#include "rtimage.h" - -using namespace rtengine; -using namespace rtengine::procparams; - -extern Glib::ustring argv0; - -PartialPasteDlg* ProfilePanel::partialProfileDlg; - - -void ProfilePanel::init () { - partialProfileDlg = new PartialPasteDlg("Foo"); -} - -void ProfilePanel::cleanup () { - delete partialProfileDlg; -} - -ProfilePanel::ProfilePanel (bool readOnly) { - - tpc = NULL; - - profiles = Gtk::manage (new MyComboBoxText ()); - Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); - hbox->show (); -// pack_start (*profiles, Gtk::PACK_SHRINK, 4); - - pack_start (*hbox, Gtk::PACK_SHRINK, 4); - - load = Gtk::manage (new Gtk::Button ()); - load->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - if (!readOnly) save = Gtk::manage (new Gtk::Button ()); - if (!readOnly) save->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - if (!readOnly) copy = Gtk::manage (new Gtk::Button ()); - if (!readOnly) copy->add (*Gtk::manage (new RTImage ("edit-copy.png"))); - paste = Gtk::manage (new Gtk::Button ()); - paste->add (*Gtk::manage (new RTImage ("edit-paste.png"))); - - hbox->pack_start (*profiles); - hbox->pack_start (*load, Gtk::PACK_SHRINK, 1); - if (!readOnly) hbox->pack_start (*save, Gtk::PACK_SHRINK, 1); - hbox->pack_start (*copy, Gtk::PACK_SHRINK, 1); - if (!readOnly) hbox->pack_start (*paste, Gtk::PACK_SHRINK, 1); - - load->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::load_clicked) ); - if (!readOnly) save->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::save_clicked) ); - if (!readOnly) copy->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::copy_clicked) ); - paste->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::paste_clicked) ); - - custom = NULL; - lastsaved = NULL; - dontupdate = false; - - refreshProfileList (); - - profiles->set_active (0); - old = profiles->get_active_text(); - changeconn = profiles->signal_changed().connect( sigc::mem_fun(*this, &ProfilePanel::selection_changed) ); - - load->set_tooltip_text (M("PROFILEPANEL_TOOLTIPLOAD")); - if (!readOnly) save->set_tooltip_text (M("PROFILEPANEL_TOOLTIPSAVE")); - if (!readOnly) copy->set_tooltip_text (M("PROFILEPANEL_TOOLTIPCOPY")); - paste->set_tooltip_text (M("PROFILEPANEL_TOOLTIPPASTE")); - - show_all_children (); -} - -ProfilePanel::~ProfilePanel () { - - if (custom) { custom->deleteInstance(); delete custom; } - if (lastsaved) { lastsaved->deleteInstance(); delete lastsaved; } -} - -void ProfilePanel::refreshProfileList () { - - Glib::ustring oldsel = profiles->get_active_text (); - changeconn.block (true); - - // clear items - profiles->clear_items (); - pparams.clear (); - - // re-parse profile directories (deletes old ones) - profileStore.parseProfiles (); - pparams = profileStore.getProfileNames (); - for (unsigned int i=0; iappend_text (pparams[i]); - - if (custom) - profiles->append_text (Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"); - if (lastsaved) - profiles->append_text (Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")"); - - profiles->set_active_text (oldsel); - changeconn.block (false); -} - -void ProfilePanel::save_clicked (GdkEventButton* event) { - - if (event->button != 1) - return; - - Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); - if (options.loadSaveProfilePath.length()) - dialog.set_current_folder (options.loadSaveProfilePath); - else - dialog.set_current_folder (options.getPreferredProfilePath()); - - //Add response buttons the the dialog: - dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); - - //Add filters, so that only certain file types can be selected: - - Gtk::FileFilter filter_pp; - filter_pp.set_name(M("PROFILEPANEL_FILEDLGFILTERPP")); - filter_pp.add_pattern("*"+paramFileExtension); - dialog.add_filter(filter_pp); - - Gtk::FileFilter filter_any; - filter_any.set_name(M("PROFILEPANEL_FILEDLGFILTERANY")); - filter_any.add_pattern("*"); - dialog.add_filter(filter_any); - -// dialog.set_do_overwrite_confirmation (true); - - savedialog = &dialog; - - bool done = false; - do { - int result = dialog.run(); - dialog.hide(); - - if (result==Gtk::RESPONSE_OK) { - - std::string fname = dialog.get_filename(); - options.loadSaveProfilePath = Glib::path_get_dirname(fname); - - bool hasext = true; - size_t dotpos = fname.find_last_of ('.'); - if (dotpos==Glib::ustring::npos) - hasext = false; - size_t dirpos1 = fname.find_last_of ('/'); - if (dirpos1!=Glib::ustring::npos && dirpos1>dotpos) - hasext = false; - size_t dirpos2 = fname.find_last_of ('\\'); - if (dirpos2!=Glib::ustring::npos && dirpos2>dotpos) - hasext = false; - - if (!hasext) - fname = fname + paramFileExtension; - - if (safe_file_test (fname, Glib::FILE_TEST_EXISTS)) { - Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + ""; - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); - int response = msgd.run (); - if (response==Gtk::RESPONSE_NO) - // make another try - continue; - } - - PartialProfile* toSave = NULL; - if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")") - toSave = custom; - else if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")") - toSave = lastsaved; - else - toSave = profileStore.getProfile (profiles->get_active_text()); - - if (toSave) { - if (event->state & Gdk::CONTROL_MASK) { - // opening the partial paste dialog window - partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) - return; - - // saving the partial profile - PartialProfile ppTemp(true); - partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); - ppTemp.pparams->save (fname, "", ppTemp.pedited); - ppTemp.deleteInstance(); - } - else { - // saving a full profile - toSave->pparams->save (fname); - } - refreshProfileList (); - } - } - done = true; - } while (!done); - return; -} - -/* - * Copy the actual full profile to the clipboard - */ -void ProfilePanel::copy_clicked (GdkEventButton* event) { - - if (event->button != 1) - return; - - PartialProfile* toSave = NULL; - if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")") - toSave = custom; - else if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")") - toSave = lastsaved; - else - toSave = profileStore.getProfile (profiles->get_active_text()); - - // toSave has to be a complete procparams - if (toSave) { - if (event->state & Gdk::CONTROL_MASK) { - // opening the partial paste dialog window - partialProfileDlg->set_title(M("PROFILEPANEL_COPYPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) - return; - - // saving a partial profile - PartialProfile ppTemp(true); - partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); - clipboard.setPartialProfile(ppTemp); - ppTemp.deleteInstance(); - } - else - clipboard.setProcParams (*toSave->pparams); - } - return; -} - -/* - * Load a potentially partial profile - */ -void ProfilePanel::load_clicked (GdkEventButton* event) { - - if (event->button != 1) - return; - - Gtk::FileChooserDialog dialog(M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); - if (options.loadSaveProfilePath.length()) - dialog.set_current_folder (options.loadSaveProfilePath); - else - dialog.set_current_folder (options.getPreferredProfilePath()); - - //Add response buttons the the dialog: - dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_OK); - - //Add filters, so that only certain file types can be selected: - - Gtk::FileFilter filter_pp; - filter_pp.set_name(M("PROFILEPANEL_FILEDLGFILTERPP")); - filter_pp.add_pattern("*"+paramFileExtension); - dialog.add_filter(filter_pp); - - Gtk::FileFilter filter_any; - filter_any.set_name(M("PROFILEPANEL_FILEDLGFILTERANY")); - filter_any.add_pattern("*"); - dialog.add_filter(filter_any); - - int result = dialog.run(); - dialog.hide(); - - if (result==Gtk::RESPONSE_OK) { - Glib::ustring fname = dialog.get_filename(); - options.loadSaveProfilePath = Glib::path_get_dirname(fname); - - if (event->state & Gdk::CONTROL_MASK) { - // opening the partial paste dialog window - partialProfileDlg->set_title(M("PROFILEPANEL_LOADPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) - return; - } - bool customCreated = false; - if (!custom) { - custom = new PartialProfile (true); - custom->set(true); - customCreated = true; - } - int err = custom->load (fname); - if (!err) { - bool prevState = changeconn.block(true); - Glib::ustring newEntry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; - profiles->append_text (newEntry); - profiles->set_active_text (newEntry); - old = profiles->get_active_text(); - changeconn.block(prevState); - - if (event->state & Gdk::CONTROL_MASK) { - // applying partial profile - PartialProfile ppTemp(true); - // the 2 next line modify custom->pedited without modifying custom->pparams - partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, custom->pparams, custom->pedited); - *custom->pedited = *ppTemp.pedited; - ppTemp.deleteInstance(); - } - - changeTo (custom, M("PROFILEPANEL_PFILE")); - } - else if (customCreated) { - // we delete custom - custom->deleteInstance(); - delete custom; - } - } - return; -} - -/* - * Paste a full profile from the clipboard - */ -void ProfilePanel::paste_clicked (GdkEventButton* event) { - - if (event->button != 1) - return; - if (!clipboard.hasProcParams()) - return; - - if (event->state & Gdk::CONTROL_MASK) { - partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) - return; - } - - bool prevState = changeconn.block(true); - Glib::ustring newEntry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; - - if (!custom) { - custom = new PartialProfile (true); - custom->pedited->set(true); - profiles->append_text (newEntry); - } - ProcParams pp = clipboard.getProcParams (); - *custom->pparams = pp; - - profiles->set_active_text (newEntry); - old = profiles->get_active_text(); - - changeconn.block(prevState); - - if (event->state & Gdk::CONTROL_MASK) { - // applying partial profile - PartialProfile ppTemp(true); - // the 2 next line modify custom->pedited without modifying custom->pparams - partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, custom->pparams, custom->pedited); - *custom->pedited = *ppTemp.pedited; - ppTemp.deleteInstance(); - } - - changeTo (custom, M("HISTORY_FROMCLIPBOARD")); - return; -} - -void ProfilePanel::changeTo (PartialProfile* newpp, Glib::ustring profname) { - - if (!newpp) - return; - - if (tpc) - tpc->profileChange (newpp, EvProfileChanged, profname); -} - -void ProfilePanel::selection_changed () { - - Glib::ustring entry; - if (profiles->get_active_text() == (entry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")")) { - if (!dontupdate) - changeTo (custom, entry); - } - else if (profiles->get_active_text() == (entry = Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")")) - changeTo (lastsaved, entry); - else { - PartialProfile* s = profileStore.getProfile (profiles->get_active_text()); - if (s) - changeTo (s, profiles->get_active_text()); - } - old = profiles->get_active_text (); - dontupdate = false; -} - -void ProfilePanel::procParamsChanged (rtengine::procparams::ProcParams* p, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { - - // to prevent recursion, filter out the events caused by the profilepanel - if (ev==EvProfileChanged || ev==EvPhotoLoaded) - return; - - Glib::ustring entry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; - if (profiles->get_active_text() != entry) { - dontupdate = true; - if (!custom) { - custom = new PartialProfile (true); - custom->set(true); - profiles->append_text (entry); - } - profiles->set_active_text (entry); - old = profiles->get_active_text(); - } - *custom->pparams = *p; -} - -void ProfilePanel::initProfile (const Glib::ustring& profname, ProcParams* lastSaved) { - - changeconn.block (true); - - profiles->clear_items (); - pparams.clear (); - - pparams = profileStore.getProfileNames (); - for (unsigned int i=0; iappend_text (pparams[i]); - - if (custom) { - custom->deleteInstance(); - delete custom; custom = NULL; - } - - if (lastsaved) { - lastsaved->deleteInstance(); - delete lastsaved; lastsaved = NULL; - } - if (lastSaved) { - ParamsEdited* pe = new ParamsEdited(); - pe->set(true); - lastsaved = new PartialProfile(lastSaved, pe); - } - - Glib::ustring defline = profname; - PartialProfile* defprofile = profileStore.getProfile (profname); - - if (lastsaved) { - defline = Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")"; - defprofile = lastsaved; - profiles->append_text (defline); - } - - if (tpc) { - if (lastsaved) - tpc->setDefaults (lastsaved->pparams); - else - tpc->setDefaults (profileStore.getProfile (profname)->pparams); - } - if (defprofile) { - old = defline; - profiles->set_active_text (defline); - changeconn.block (false); - if (tpc) - tpc->profileChange (defprofile, EvPhotoLoaded, defline); - } - else { - bool dels = false; - // select first valid profile - old = ""; - 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, cProfile); - } - - if (dels) { - s->deleteInstance(); - delete s; - } - } -} - - - +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "profilepanel.h" +#include "options.h" +#include "profilestore.h" +#include "clipboard.h" +#include "multilangmgr.h" +#include "../rtengine/safegtk.h" +#include "rtimage.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +extern Glib::ustring argv0; + +PartialPasteDlg* ProfilePanel::partialProfileDlg; + + +void ProfilePanel::init () { + partialProfileDlg = new PartialPasteDlg("Foo"); +} + +void ProfilePanel::cleanup () { + delete partialProfileDlg; +} + +ProfilePanel::ProfilePanel (bool readOnly) { + + tpc = NULL; + + profiles = Gtk::manage (new MyComboBoxText ()); + Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); + hbox->show (); +// pack_start (*profiles, Gtk::PACK_SHRINK, 4); + + pack_start (*hbox, Gtk::PACK_SHRINK, 4); + + load = Gtk::manage (new Gtk::Button ()); + load->add (*Gtk::manage (new RTImage ("gtk-open.png"))); + if (!readOnly) save = Gtk::manage (new Gtk::Button ()); + if (!readOnly) save->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + if (!readOnly) copy = Gtk::manage (new Gtk::Button ()); + if (!readOnly) copy->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + paste = Gtk::manage (new Gtk::Button ()); + paste->add (*Gtk::manage (new RTImage ("edit-paste.png"))); + + hbox->pack_start (*profiles); + hbox->pack_start (*load, Gtk::PACK_SHRINK, 1); + if (!readOnly) hbox->pack_start (*save, Gtk::PACK_SHRINK, 1); + hbox->pack_start (*copy, Gtk::PACK_SHRINK, 1); + if (!readOnly) hbox->pack_start (*paste, Gtk::PACK_SHRINK, 1); + + load->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::load_clicked) ); + if (!readOnly) save->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::save_clicked) ); + if (!readOnly) copy->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::copy_clicked) ); + paste->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::paste_clicked) ); + + custom = NULL; + lastsaved = NULL; + dontupdate = false; + + refreshProfileList (); + + profiles->set_active (0); + old = profiles->get_active_text(); + changeconn = profiles->signal_changed().connect( sigc::mem_fun(*this, &ProfilePanel::selection_changed) ); + + load->set_tooltip_text (M("PROFILEPANEL_TOOLTIPLOAD")); + if (!readOnly) save->set_tooltip_text (M("PROFILEPANEL_TOOLTIPSAVE")); + if (!readOnly) copy->set_tooltip_text (M("PROFILEPANEL_TOOLTIPCOPY")); + paste->set_tooltip_text (M("PROFILEPANEL_TOOLTIPPASTE")); + + show_all_children (); +} + +ProfilePanel::~ProfilePanel () { + + if (custom) { custom->deleteInstance(); delete custom; } + if (lastsaved) { lastsaved->deleteInstance(); delete lastsaved; } +} + +void ProfilePanel::refreshProfileList () { + + Glib::ustring oldsel = profiles->get_active_text (); + changeconn.block (true); + + // clear items + profiles->clear_items (); + pparams.clear (); + + // re-parse profile directories (deletes old ones) + profileStore.parseProfiles (); + pparams = profileStore.getProfileNames (); + for (unsigned int i=0; iappend_text (pparams[i]); + + if (custom) + profiles->append_text (Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"); + if (lastsaved) + profiles->append_text (Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")"); + + profiles->set_active_text (oldsel); + changeconn.block (false); +} + +void ProfilePanel::save_clicked (GdkEventButton* event) { + + if (event->button != 1) + return; + + Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); + FileChooserLastFolderPersister persister( &dialog, options.loadSaveProfilePath ); + + //Add response buttons the the dialog: + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); + + //Add filters, so that only certain file types can be selected: + + Gtk::FileFilter filter_pp; + filter_pp.set_name(M("PROFILEPANEL_FILEDLGFILTERPP")); + filter_pp.add_pattern("*"+paramFileExtension); + dialog.add_filter(filter_pp); + + Gtk::FileFilter filter_any; + filter_any.set_name(M("PROFILEPANEL_FILEDLGFILTERANY")); + filter_any.add_pattern("*"); + dialog.add_filter(filter_any); + +// dialog.set_do_overwrite_confirmation (true); + + savedialog = &dialog; + + bool done = false; + do { + int result = dialog.run(); + dialog.hide(); + + if (result==Gtk::RESPONSE_OK) { + + std::string fname = dialog.get_filename(); + + bool hasext = true; + size_t dotpos = fname.find_last_of ('.'); + if (dotpos==Glib::ustring::npos) + hasext = false; + size_t dirpos1 = fname.find_last_of ('/'); + if (dirpos1!=Glib::ustring::npos && dirpos1>dotpos) + hasext = false; + size_t dirpos2 = fname.find_last_of ('\\'); + if (dirpos2!=Glib::ustring::npos && dirpos2>dotpos) + hasext = false; + + if (!hasext) + fname = fname + paramFileExtension; + + if (safe_file_test (fname, Glib::FILE_TEST_EXISTS)) { + Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + ""; + Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); + int response = msgd.run (); + if (response==Gtk::RESPONSE_NO) + // make another try + continue; + } + + PartialProfile* toSave = NULL; + if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")") + toSave = custom; + else if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")") + toSave = lastsaved; + else + toSave = profileStore.getProfile (profiles->get_active_text()); + + if (toSave) { + if (event->state & Gdk::CONTROL_MASK) { + // opening the partial paste dialog window + partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + if (i != Gtk::RESPONSE_OK) + return; + + // saving the partial profile + PartialProfile ppTemp(true); + partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); + ppTemp.pparams->save (fname, "", ppTemp.pedited); + ppTemp.deleteInstance(); + } + else { + // saving a full profile + toSave->pparams->save (fname); + } + refreshProfileList (); + } + } + done = true; + } while (!done); + return; +} + +/* + * Copy the actual full profile to the clipboard + */ +void ProfilePanel::copy_clicked (GdkEventButton* event) { + + if (event->button != 1) + return; + + PartialProfile* toSave = NULL; + if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")") + toSave = custom; + else if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")") + toSave = lastsaved; + else + toSave = profileStore.getProfile (profiles->get_active_text()); + + // toSave has to be a complete procparams + if (toSave) { + if (event->state & Gdk::CONTROL_MASK) { + // opening the partial paste dialog window + partialProfileDlg->set_title(M("PROFILEPANEL_COPYPPASTE")); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + if (i != Gtk::RESPONSE_OK) + return; + + // saving a partial profile + PartialProfile ppTemp(true); + partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); + clipboard.setPartialProfile(ppTemp); + ppTemp.deleteInstance(); + } + else + clipboard.setProcParams (*toSave->pparams); + } + return; +} + +/* + * Load a potentially partial profile + */ +void ProfilePanel::load_clicked (GdkEventButton* event) { + + if (event->button != 1) + return; + + Gtk::FileChooserDialog dialog(M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); + FileChooserLastFolderPersister persister( &dialog, options.loadSaveProfilePath ); + + //Add response buttons the the dialog: + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_OK); + + //Add filters, so that only certain file types can be selected: + + Gtk::FileFilter filter_pp; + filter_pp.set_name(M("PROFILEPANEL_FILEDLGFILTERPP")); + filter_pp.add_pattern("*"+paramFileExtension); + dialog.add_filter(filter_pp); + + Gtk::FileFilter filter_any; + filter_any.set_name(M("PROFILEPANEL_FILEDLGFILTERANY")); + filter_any.add_pattern("*"); + dialog.add_filter(filter_any); + + int result = dialog.run(); + dialog.hide(); + + if (result==Gtk::RESPONSE_OK) { + Glib::ustring fname = dialog.get_filename(); + + if (event->state & Gdk::CONTROL_MASK) { + // opening the partial paste dialog window + partialProfileDlg->set_title(M("PROFILEPANEL_LOADPPASTE")); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + if (i != Gtk::RESPONSE_OK) + return; + } + bool customCreated = false; + if (!custom) { + custom = new PartialProfile (true); + custom->set(true); + customCreated = true; + } + int err = custom->load (fname); + if (!err) { + bool prevState = changeconn.block(true); + Glib::ustring newEntry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; + profiles->append_text (newEntry); + profiles->set_active_text (newEntry); + old = profiles->get_active_text(); + changeconn.block(prevState); + + if (event->state & Gdk::CONTROL_MASK) { + // applying partial profile + PartialProfile ppTemp(true); + // the 2 next line modify custom->pedited without modifying custom->pparams + partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, custom->pparams, custom->pedited); + *custom->pedited = *ppTemp.pedited; + ppTemp.deleteInstance(); + } + + changeTo (custom, M("PROFILEPANEL_PFILE")); + } + else if (customCreated) { + // we delete custom + custom->deleteInstance(); + delete custom; + } + } + return; +} + +/* + * Paste a full profile from the clipboard + */ +void ProfilePanel::paste_clicked (GdkEventButton* event) { + + if (event->button != 1) + return; + if (!clipboard.hasProcParams()) + return; + + if (event->state & Gdk::CONTROL_MASK) { + partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); + int i = partialProfileDlg->run(); + partialProfileDlg->hide(); + if (i != Gtk::RESPONSE_OK) + return; + } + + bool prevState = changeconn.block(true); + Glib::ustring newEntry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; + + if (!custom) { + custom = new PartialProfile (true); + custom->pedited->set(true); + profiles->append_text (newEntry); + } + ProcParams pp = clipboard.getProcParams (); + *custom->pparams = pp; + + profiles->set_active_text (newEntry); + old = profiles->get_active_text(); + + changeconn.block(prevState); + + if (event->state & Gdk::CONTROL_MASK) { + // applying partial profile + PartialProfile ppTemp(true); + // the 2 next line modify custom->pedited without modifying custom->pparams + partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, custom->pparams, custom->pedited); + *custom->pedited = *ppTemp.pedited; + ppTemp.deleteInstance(); + } + + changeTo (custom, M("HISTORY_FROMCLIPBOARD")); + return; +} + +void ProfilePanel::changeTo (PartialProfile* newpp, Glib::ustring profname) { + + if (!newpp) + return; + + if (tpc) + tpc->profileChange (newpp, EvProfileChanged, profname); +} + +void ProfilePanel::selection_changed () { + + Glib::ustring entry; + if (profiles->get_active_text() == (entry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")")) { + if (!dontupdate) + changeTo (custom, entry); + } + else if (profiles->get_active_text() == (entry = Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")")) + changeTo (lastsaved, entry); + else { + PartialProfile* s = profileStore.getProfile (profiles->get_active_text()); + if (s) + changeTo (s, profiles->get_active_text()); + } + old = profiles->get_active_text (); + dontupdate = false; +} + +void ProfilePanel::procParamsChanged (rtengine::procparams::ProcParams* p, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { + + // to prevent recursion, filter out the events caused by the profilepanel + if (ev==EvProfileChanged || ev==EvPhotoLoaded) + return; + + Glib::ustring entry = Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")"; + if (profiles->get_active_text() != entry) { + dontupdate = true; + if (!custom) { + custom = new PartialProfile (true); + custom->set(true); + profiles->append_text (entry); + } + profiles->set_active_text (entry); + old = profiles->get_active_text(); + } + *custom->pparams = *p; +} + +void ProfilePanel::initProfile (const Glib::ustring& profname, ProcParams* lastSaved) { + + changeconn.block (true); + + profiles->clear_items (); + pparams.clear (); + + pparams = profileStore.getProfileNames (); + for (unsigned int i=0; iappend_text (pparams[i]); + + if (custom) { + custom->deleteInstance(); + delete custom; custom = NULL; + } + + if (lastsaved) { + lastsaved->deleteInstance(); + delete lastsaved; lastsaved = NULL; + } + if (lastSaved) { + ParamsEdited* pe = new ParamsEdited(); + pe->set(true); + lastsaved = new PartialProfile(lastSaved, pe); + } + + Glib::ustring defline = profname; + PartialProfile* defprofile = profileStore.getProfile (profname); + + if (lastsaved) { + defline = Glib::ustring("(") + M("PROFILEPANEL_PLASTSAVED") + ")"; + defprofile = lastsaved; + profiles->append_text (defline); + } + + if (tpc) { + if (lastsaved) + tpc->setDefaults (lastsaved->pparams); + else + tpc->setDefaults (profileStore.getProfile (profname)->pparams); + } + if (defprofile) { + old = defline; + profiles->set_active_text (defline); + changeconn.block (false); + if (tpc) + tpc->profileChange (defprofile, EvPhotoLoaded, defline); + } + else { + bool dels = false; + // select first valid profile + old = ""; + 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, cProfile); + } + + if (dels) { + s->deleteInstance(); + delete s; + } + } +} + + + diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc index 03b4979d9..5c534228b 100644 --- a/rtgui/rgbcurves.cc +++ b/rtgui/rgbcurves.cc @@ -24,7 +24,7 @@ using namespace rtengine::procparams; RGBCurves::RGBCurves () : Gtk::VBox(), FoldableToolPanel(this) { - curveEditorG = new CurveEditorGroup (M("TP_RGBCURVES_CHANNEL")); + curveEditorG = new CurveEditorGroup (options.lastRgbCurvesDir, M("TP_RGBCURVES_CHANNEL")); curveEditorG->setCurveListener (this); curveEditorG->setColorProvider (this); diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 594115f56..2c0d93d35 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -85,7 +85,7 @@ ToneCurve::ToneCurve () : Gtk::VBox(), FoldableToolPanel(this) { //----------- Curve ------------------------------ pack_start (*Gtk::manage (new Gtk::HSeparator())); - curveEditorG = new CurveEditorGroup (M("TP_EXPOSURE_CURVEEDITOR")); + curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR")); curveEditorG->setCurveListener (this); shape = static_cast(curveEditorG->addCurve(CT_Diagonal, ""));