From 218231848c3847a4060ec845f68c44cbd07a99ee Mon Sep 17 00:00:00 2001 From: DrSlony Date: Sat, 7 Jul 2012 23:00:28 +0100 Subject: [PATCH] Enhancement of all file save dialogs. Committed on behalf of Sankey, issue 1314 --- rtdata/languages/default | 2 + rtgui/curveeditorgroup.cc | 42 +++++-------- rtgui/curveeditorgroup.h | 1 + rtgui/editorpanel.cc | 67 ++++++++++++--------- rtgui/editorpanel.h | 5 +- rtgui/guiutils.cc | 19 +++++- rtgui/guiutils.h | 1 + rtgui/icmpanel.cc | 31 ++++++++-- rtgui/icmpanel.h | 1 + rtgui/options.cc | 5 ++ rtgui/options.h | 1 + rtgui/profilepanel.cc | 36 +++--------- rtgui/profilepanel.h | 6 +- rtgui/saveasdlg.cc | 121 +++++++++++++++++++++++++------------- rtgui/saveasdlg.h | 10 ++-- 15 files changed, 212 insertions(+), 136 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index d46bed96f..9fe4abce3 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -203,6 +203,7 @@ GENERAL_PORTRAIT;Portrait GENERAL_SAVE;Save GENERAL_UNCHANGED;(Unchanged) GENERAL_YES;Yes +GENERAL_WARNING;Warning HISTOGRAM_BUTTON_BAR;RGB HISTOGRAM_BUTTON_B;B HISTOGRAM_BUTTON_G;G @@ -804,6 +805,7 @@ SAVEDLG_SAVEIMMEDIATELY;Save immediately SAVEDLG_SAVESPP;Save processing parameters with image SAVEDLG_TIFFFILTER;TIFF files SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF +SAVEDLG_WARNFILENAME;File will be named THRESHOLDSELECTOR_B;Bottom THRESHOLDSELECTOR_BL;Bottom-left THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index 8ffc6441d..aae30196a 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -295,13 +295,14 @@ void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) { } CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : - curveDir(curveDir) { + curveDir(curveDir), lastFilename("") { } Glib::ustring CurveEditorSubGroup::outputFile () { Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister(&dialog, curveDir); + dialog.set_current_name (lastFilename); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_APPLY); @@ -316,33 +317,22 @@ Glib::ustring CurveEditorSubGroup::outputFile () { filter_any.add_pattern("*"); dialog.add_filter(filter_any); - dialog.set_do_overwrite_confirmation (true); + //dialog.set_do_overwrite_confirmation (true); - Glib::ustring fname; + Glib::ustring fname; do { - int result = dialog.run(); - - fname = dialog.get_filename(); - - if (result==Gtk::RESPONSE_APPLY) { - - if (getExtension (fname)!="rtc") - fname = fname + ".rtc"; - - 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_YES) - break; - } - else - break; - } - else { - fname = ""; - break; - } + if (dialog.run() == Gtk::RESPONSE_APPLY) { + fname = dialog.get_filename(); + if (getExtension (fname) != "rtc") + fname += ".rtc"; + if (confirmOverwrite (dialog, fname)) { + lastFilename = Glib::path_get_basename (fname); + break; + } + } else { + fname = ""; + break; + } } while (1); return fname; diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index 27c5268df..6cec43e0c 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -98,6 +98,7 @@ class CurveEditorSubGroup { private: Glib::ustring& curveDir; + Glib::ustring lastFilename; protected: int valLinear; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 0f45bd275..01141df55 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -258,7 +258,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) updateHistogramPosition (0, options.histogramPosition); show_all (); - +/* // save as dialog if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); @@ -266,7 +266,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); - +*/ // connect listeners profilep->setProfileChangeListener (tpc); history->setProfileChangeListener (tpc); @@ -329,7 +329,7 @@ EditorPanel::~EditorPanel () { delete ppframe; delete leftbox; delete vboxright; - delete saveAsDialog; + //delete saveAsDialog; if(catalogPane) delete catalogPane; } @@ -382,6 +382,8 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { openThm->increaseRef (); fname=openThm->getFileName(); + //saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (fname))); + lastSaveAsFileName = removeExtension (Glib::path_get_basename (fname)); previewHandler = new PreviewHandler (); @@ -407,7 +409,8 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { // initialize profile Glib::ustring defProf = openThm->getType()==FT_Raw ? options.defProfRaw : options.defProfImg; - profilep->initProfile (defProf, ldprof); + profilep->initProfile (defProf, ldprof); + profilep->setInitialFileName (Glib::path_get_basename (fname) + paramFileExtension); openThm->addThumbnailListener (this); info_toggled (); @@ -1016,42 +1019,52 @@ BatchQueueEntry* EditorPanel::createBatchQueueEntry () { void EditorPanel::saveAsPressed () { if (!ipc || !openThm) return; bool fnameOK = false; - Glib::ustring fname; + Glib::ustring fnameOut; + + SaveAsDialog* saveAsDialog; + if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); + else + saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); + + saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); + saveAsDialog->setInitialFileName (lastSaveAsFileName); - saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName()))); do { - saveAsDialog->run (); - if (saveAsDialog->getResponse()!=Gtk::RESPONSE_OK) - return; + int result = saveAsDialog->run (); // The SaveAsDialog ensure that a filename has been specified - fname = saveAsDialog->getFileName (); + fnameOut = saveAsDialog->getFileName (); options.lastSaveAsPath = saveAsDialog->getDirectory (); - options.saveAsDialogWidth = saveAsDialog->get_width(); - options.saveAsDialogHeight = saveAsDialog->get_height(); - + options.saveAsDialogWidth = saveAsDialog->get_width (); + options.saveAsDialogHeight = saveAsDialog->get_height (); + options.autoSuffix = saveAsDialog->getAutoSuffix (); + options.saveMethodNum = saveAsDialog->getSaveMethodNum (); + lastSaveAsFileName = Glib::path_get_basename (removeExtension (fnameOut)); SaveFormat sf = saveAsDialog->getFormat (); - options.saveFormat = sf; - options.autoSuffix = saveAsDialog->getAutoSuffix(); + + if (result != Gtk::RESPONSE_OK) + break; if (saveAsDialog->getImmediately ()) { // separate filename and the path to the destination directory - Glib::ustring dstdir = Glib::path_get_dirname (fname); - Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fname)); + Glib::ustring dstdir = Glib::path_get_dirname (fnameOut); + Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fnameOut)); + Glib::ustring dstext = getExtension (fnameOut); if (saveAsDialog->getAutoSuffix()) { Glib::ustring fnameTemp; for (int tries=0; tries<100; tries++) { if (tries==0) - fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), sf.format); + fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), dstext); else - fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, sf.format); + fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext); if (!safe_file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { - fname = fnameTemp; + fnameOut = fnameTemp; fnameOK = true; break; } @@ -1059,13 +1072,7 @@ void EditorPanel::saveAsPressed () { } // check if it exists if (!fnameOK) { - 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 (*parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); - int response = msgd.run (); - fnameOK = (response==Gtk::RESPONSE_YES); - } - else fnameOK = true; + fnameOK = confirmOverwrite (*saveAsDialog, fnameOut); } if (fnameOK) { @@ -1076,14 +1083,14 @@ void EditorPanel::saveAsPressed () { ProgressConnector *ld = new ProgressConnector(); ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fname,sf )); + sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fnameOut,sf )); saveimgas->set_sensitive(false); sendtogimp->set_sensitive(false); } } else { BatchQueueEntry* bqe = createBatchQueueEntry (); - bqe->outFileName = fname; + bqe->outFileName = fnameOut; bqe->saveFormat = saveAsDialog->getFormat (); parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); fnameOK = true; @@ -1091,6 +1098,8 @@ void EditorPanel::saveAsPressed () { // ask parent to redraw file browser // ... or does it automatically when the tab is switched to it } while (!fnameOK); + + saveAsDialog->hide(); } void EditorPanel::queueImgPressed () { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index e0e12e999..2d5316aac 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -49,6 +49,9 @@ class EditorPanel : public Gtk::VBox, public ThumbnailListener, public HistoryBeforeLineListener, public rtengine::HistogramListener { + private: + + Glib::ustring lastSaveAsFileName; protected: Gtk::ProgressBar *progressLabel; @@ -97,7 +100,7 @@ class EditorPanel : public Gtk::VBox, HistogramPanel* histogramPanel; ToolPanelCoordinator* tpc; RTWindow* parent; - SaveAsDialog* saveAsDialog; + //SaveAsDialog* saveAsDialog; BatchToolPanelCoordinator* btpCoordinator; FilePanel* fPanel; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index e8b00cee7..1c4fb9683 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -20,7 +20,9 @@ #include "guiutils.h" #include "options.h" #include "../rtengine/utils.h" +#include "../rtengine/safegtk.h" #include "rtimage.h" +#include "multilangmgr.h" #include @@ -53,7 +55,8 @@ Glib::ustring removeExtension (const Glib::ustring& filename) { Glib::ustring bname = Glib::path_get_basename(filename); size_t lastdot = bname.find_last_of ('.'); - if (lastdot!=bname.npos) + size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); + if (lastdot!=bname.npos && (lastwhitespace==bname.npos || lastdot > lastwhitespace)) return filename.substr (0, filename.size()-(bname.size()-lastdot)); else return filename; @@ -63,12 +66,24 @@ Glib::ustring getExtension (const Glib::ustring& filename) { Glib::ustring bname = Glib::path_get_basename(filename); size_t lastdot = bname.find_last_of ('.'); - if (lastdot!=bname.npos) + size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); + if (lastdot!=bname.npos && (lastwhitespace==bname.npos || lastdot > lastwhitespace)) return filename.substr (filename.size()-(bname.size()-lastdot)+1, filename.npos); else return ""; } +bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { + bool safe = true; + if (safe_file_test (filename, Glib::FILE_TEST_EXISTS)) { + Glib::ustring msg_ = Glib::ustring ("\"") + Glib::path_get_basename (filename) + "\": " + + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE"); + Gtk::MessageDialog msgd (parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); + safe = (msgd.run () == Gtk::RESPONSE_YES); + } + return safe; +} + void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams) { cr->set_line_width (0.); diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index 9bbeef28c..1f48502b5 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -26,6 +26,7 @@ bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference=true void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); Glib::ustring removeExtension (const Glib::ustring& filename); Glib::ustring getExtension (const Glib::ustring& filename); +bool confirmOverwrite (Gtk::Window& parent, const std::string& filename); void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams); /** diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index dc77bc980..14f87baec 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -30,7 +30,7 @@ using namespace rtengine::procparams; extern Options options; -ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), icmplistener(NULL) { +ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), icmplistener(NULL), lastRefFilename("") { // set_border_width (4); @@ -484,6 +484,7 @@ void ICMPanel::saveReferencePressed () { return; Gtk::FileChooserDialog dialog(M("TP_ICM_SAVEREFERENCEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister(&dialog, options.lastProfilingReferenceDir); + dialog.set_current_name (lastRefFilename); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); @@ -491,12 +492,34 @@ void ICMPanel::saveReferencePressed () { Gtk::FileFilter filter_tif; filter_tif.set_name(M("SAVEDLG_TIFFFILTER")); filter_tif.add_pattern("*.tif"); + filter_tif.add_pattern("*.tiff"); dialog.add_filter(filter_tif); - dialog.set_do_overwrite_confirmation (true); + Gtk::FileFilter filter_any; + filter_any.set_name(M("TP_ICM_FILEDLGFILTERANY")); + filter_any.add_pattern("*"); + dialog.add_filter(filter_any); - if (dialog.run()==Gtk::RESPONSE_OK) - icmplistener->saveInputICCReference (dialog.get_filename()); + //dialog.set_do_overwrite_confirmation (true); + + bool done = false; + do { + int result = dialog.run(); + if (result != Gtk::RESPONSE_OK) { + done = true; + } else { + std::string fname = dialog.get_filename(); + Glib::ustring ext = getExtension(fname); + if (ext != "tif" && ext != "tiff") + fname += ".tif"; + if (confirmOverwrite(dialog, fname)) { + icmplistener->saveInputICCReference (fname); + lastRefFilename = Glib::path_get_basename (fname); + done = true; + } + } + } while (!done); + return; } void ICMPanel::setBatchMode (bool batchMode) { diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 4b3fc33a8..63fef53d5 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -68,6 +68,7 @@ class ICMPanel : public Gtk::VBox, public AdjusterListener, public FoldableToolP ICMPanelListener* icmplistener; bool enableLastICCWorkDirChange; + Glib::ustring lastRefFilename; public: ICMPanel (); diff --git a/rtgui/options.cc b/rtgui/options.cc index 30a433851..7135f7f3c 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -190,6 +190,8 @@ void Options::setDefaults () { windowWidth = 900; windowHeight = 560; windowMaximized = false; + saveAsDialogWidth = 600; + saveAsDialogHeight = 600; savesParamsAtExit = true; saveFormat.format = "jpg"; saveFormat.jpegQuality = 100; @@ -262,6 +264,7 @@ void Options::setDefaults () { thumbnailFormat = FT_Custom; // was FT_Custom16 thumbInterp = 1; autoSuffix = false; + saveMethodNum = 0; // 0->immediate, 1->putToQueuHead, 2->putToQueueTail saveParamsFile = true; // was false, but saving the procparams files next to the file make more sense when reorganizing file tree than in a cache saveParamsCache = false; // there's no need to save the procparams files in a cache if saveParamsFile is true paramsLoadLocation = PLL_Input; // was PLL_Cache @@ -517,6 +520,7 @@ if (keyFile.has_group ("Output")) { if (keyFile.has_key ("Output", "PathTemplate")) savePathTemplate = keyFile.get_string ("Output", "PathTemplate"); if (keyFile.has_key ("Output", "PathFolder")) savePathFolder = keyFile.get_string ("Output", "PathFolder"); if (keyFile.has_key ("Output", "AutoSuffix")) autoSuffix = keyFile.get_boolean("Output", "AutoSuffix"); + if (keyFile.has_key ("Output", "SaveMethodNum")) saveMethodNum = keyFile.get_integer("Output", "SaveMethodNum"); if (keyFile.has_key ("Output", "UsePathTemplate")) saveUsePathTemplate = keyFile.get_boolean("Output", "UsePathTemplate"); if (keyFile.has_key ("Output", "LastSaveAsPath")) lastSaveAsPath = keyFile.get_string ("Output", "LastSaveAsPath"); if (keyFile.has_key ("Output", "OverwriteOutputFile")) overwriteOutputFile = keyFile.get_boolean("Output", "OverwriteOutputFile"); @@ -796,6 +800,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_string ("Output", "PathTemplate", savePathTemplate); keyFile.set_string ("Output", "PathFolder", savePathFolder); keyFile.set_boolean ("Output", "AutoSuffix", autoSuffix); + keyFile.set_integer ("Output", "SaveMethodNum", saveMethodNum); keyFile.set_boolean ("Output", "UsePathTemplate", saveUsePathTemplate); keyFile.set_string ("Output", "LastSaveAsPath", lastSaveAsPath); keyFile.set_boolean ("Output", "OverwriteOutputFile", overwriteOutputFile); diff --git a/rtgui/options.h b/rtgui/options.h index 3eba1a8f1..2f586c34a 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -140,6 +140,7 @@ class Options { bool useSystemTheme; static Glib::ustring cacheBaseDir; bool autoSuffix; + int saveMethodNum; bool saveParamsFile; bool saveParamsCache; PPLoadLocation paramsLoadLocation; diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index 8885ad742..de02e9ae2 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -40,7 +40,7 @@ void ProfilePanel::cleanup () { delete partialProfileDlg; } -ProfilePanel::ProfilePanel (bool readOnly) { +ProfilePanel::ProfilePanel (bool readOnly) : lastFilename("") { tpc = NULL; @@ -126,6 +126,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister( &dialog, options.loadSaveProfilePath ); + dialog.set_current_name (lastFilename); //Add response buttons the the dialog: dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); @@ -145,39 +146,20 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { // dialog.set_do_overwrite_confirmation (true); - savedialog = &dialog; - bool done = false; do { - int result = dialog.run(); - dialog.hide(); - - if (result==Gtk::RESPONSE_OK) { + if (dialog.run()==Gtk::RESPONSE_OK) { std::string fname = dialog.get_filename(); + Glib::ustring ext = getExtension (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 (("." + ext) != paramFileExtension) + fname += paramFileExtension; - if (!hasext) - fname = fname + paramFileExtension; + if (!confirmOverwrite (dialog, fname)) + continue; - 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; - } + lastFilename = Glib::path_get_basename (fname); PartialProfile* toSave = NULL; if (profiles->get_active_text() == Glib::ustring("(") + M("PROFILEPANEL_PCUSTOM") + ")") diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index b9677e8e1..e2bf6cd9c 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -29,6 +29,10 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener { + private: + + Glib::ustring lastFilename; + protected: static PartialPasteDlg* partialProfileDlg; @@ -44,7 +48,6 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener { ProfileChangeListener* tpc; bool dontupdate; sigc::connection changeconn; - Gtk::FileChooserDialog* savedialog; void changeTo (rtengine::procparams::PartialProfile* newpp, Glib::ustring profname); void refreshProfileList (); @@ -60,6 +63,7 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener { static void cleanup (); void initProfile (const Glib::ustring& profname, rtengine::procparams::ProcParams* lastSaved); + void setInitialFileName (const Glib::ustring& filename) {lastFilename = filename;} // PParamsChangeListener interface void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL); diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index df3bdaa89..e5eccb67a 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -31,60 +31,52 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { fchooser = Gtk::manage( new Gtk::FileChooserWidget (Gtk::FILE_CHOOSER_ACTION_SAVE) ); fchooser->set_current_folder (initialDir); + fchooser->signal_file_activated().connect(sigc::mem_fun(*this,&SaveAsDialog::okPressed)); filter_jpg.set_name(M("SAVEDLG_JPGFILTER")); filter_jpg.add_pattern("*.jpg"); + filter_jpg.add_pattern("*.JPG"); + filter_jpg.add_pattern("*.jpeg"); + filter_jpg.add_pattern("*.JPEG"); + filter_jpg.add_pattern("*.jpe"); + filter_jpg.add_pattern("*.JPE"); filter_tif.set_name(M("SAVEDLG_JPGFILTER")); filter_tif.add_pattern("*.tif"); + filter_tif.add_pattern("*.TIF"); + filter_tif.add_pattern("*.tiff"); + filter_tif.add_pattern("*.TIFF"); filter_png.set_name(M("SAVEDLG_JPGFILTER")); filter_png.add_pattern("*.png"); + filter_png.add_pattern("*.PNG"); - vbox->pack_start (*fchooser); - - Gtk::HSeparator* hsep1 = Gtk::manage( new Gtk::HSeparator () ); - vbox->pack_start (*hsep1, Gtk::PACK_SHRINK, 2); + formatChanged (options.saveFormat.format); // Unique filename option // ~~~~~~~~~~~~~~~~~~~~~~ autoSuffix = Gtk::manage( new Gtk::CheckButton (M("SAVEDLG_AUTOSUFFIX")) ); autoSuffix->set_active(options.autoSuffix); - vbox->pack_start (*autoSuffix, Gtk::PACK_SHRINK, 4); - - Gtk::HSeparator* hsep2 = Gtk::manage( new Gtk::HSeparator () ); - vbox->pack_start (*hsep2, Gtk::PACK_SHRINK, 2); - // Output Options // ~~~~~~~~~~~~~~ formatOpts = Gtk::manage( new SaveFormatPanel () ); formatOpts->init (options.saveFormat); formatOpts->setListener (this); - vbox->pack_start (*formatOpts, Gtk::PACK_SHRINK, 4); - - Gtk::HSeparator* hsep3 = Gtk::manage( new Gtk::HSeparator () ); - vbox->pack_start (*hsep3, Gtk::PACK_SHRINK, 2); - // queue/immediate // ~~~~~~~~~~~~~ - immediately = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_SAVEIMMEDIATELY")) ); - putToQueueHead = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_PUTTOQUEUEHEAD")) ); - putToQueueTail = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_PUTTOQUEUETAIL")) ); + saveMethod[0] = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_SAVEIMMEDIATELY")) ); + saveMethod[1] = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_PUTTOQUEUEHEAD")) ); + saveMethod[2] = Gtk::manage( new Gtk::RadioButton (M("SAVEDLG_PUTTOQUEUETAIL")) ); - // There is no queue in simple mode, so no need to choose - if (!simpleEditor) { - vbox->pack_start (*immediately, Gtk::PACK_SHRINK, 4); - vbox->pack_start (*putToQueueHead, Gtk::PACK_SHRINK, 4); - vbox->pack_start (*putToQueueTail, Gtk::PACK_SHRINK, 4); - } + Gtk::RadioButton::Group g = saveMethod[0]->get_group(); + saveMethod[1]->set_group (g); + saveMethod[2]->set_group (g); + + if (options.saveMethodNum >= 0 && options.saveMethodNum < 3) + saveMethod[options.saveMethodNum]->set_active (true); - immediately->set_active (true); - Gtk::RadioButton::Group g = immediately->get_group(); - putToQueueHead->set_group (g); - putToQueueTail->set_group (g); - // buttons // ~~~~~~ Gtk::Button* ok = Gtk::manage( new Gtk::Button (M("GENERAL_OK")) ); @@ -96,11 +88,32 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { ok->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::okPressed) ); cancel->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::cancelPressed) ); +// pack everything +// ~~~~~~~~~~~~~~~ + Gtk::VBox* vbox_bottomRight = Gtk::manage(new Gtk::VBox ()); + // There is no queue in simple mode, so no need to choose + if (!simpleEditor) { + vbox_bottomRight->pack_start (*saveMethod[0], Gtk::PACK_SHRINK, 2); + vbox_bottomRight->pack_start (*saveMethod[1], Gtk::PACK_SHRINK, 2); + vbox_bottomRight->pack_start (*saveMethod[2], Gtk::PACK_SHRINK, 2); + vbox_bottomRight->pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 5); + } + vbox_bottomRight->pack_start (*autoSuffix, Gtk::PACK_SHRINK, 4); + + Gtk::HBox* hbox_bottom = Gtk::manage( new Gtk::HBox() ); + hbox_bottom->pack_start (*formatOpts, Gtk::PACK_SHRINK, 2); + hbox_bottom->pack_start (*Gtk::manage(new Gtk::VSeparator ()), Gtk::PACK_SHRINK, 2); + hbox_bottom->pack_start (*vbox_bottomRight, Gtk::PACK_SHRINK, 2); + + vbox->pack_start (*fchooser); + vbox->pack_start (*hbox_bottom, Gtk::PACK_SHRINK, 2); + get_action_area()->pack_end (*ok, Gtk::PACK_SHRINK, 4); get_action_area()->pack_end (*cancel, Gtk::PACK_SHRINK, 4); set_border_width (4); show_all_children (); + } bool SaveAsDialog::getAutoSuffix () { @@ -110,26 +123,29 @@ bool SaveAsDialog::getAutoSuffix () { bool SaveAsDialog::getImmediately () { - return immediately->get_active (); + return saveMethod[0]->get_active (); } bool SaveAsDialog::getToHeadOfQueue () { - return putToQueueHead->get_active (); + return saveMethod[1]->get_active (); } bool SaveAsDialog::getToTailOfQueue () { - return putToQueueTail->get_active (); + return saveMethod[2]->get_active (); +} + +int SaveAsDialog::getSaveMethodNum () { + for (int i = 0; i < 3; i++) + if (saveMethod[i]->get_active()) + return i; + return -1; } Glib::ustring SaveAsDialog::getFileName () { - // fname is empty if the dialog has been cancelled - if (fname.length()) - return removeExtension(fname) + Glib::ustring(".") + formatOpts->getFormat().format; - else - return ""; + return fname; } Glib::ustring SaveAsDialog::getDirectory () { @@ -155,15 +171,38 @@ void SaveAsDialog::okPressed () { msgd.run (); return; } - response = Gtk::RESPONSE_OK; - hide (); + + // resolve extension ambiguities + SaveFormat sf = formatOpts->getFormat (); + Glib::ustring extLower = getExtension (fname).lowercase (); + bool extIsEmpty = (extLower == ""); + bool extIsJpeg = (extLower == "jpg" || extLower == "jpeg" || extLower == "jpe"); + bool extIsTiff = (extLower == "tif" || extLower == "tiff"); + bool extIsPng = (extLower == "png"); + if (extIsEmpty || !(extIsJpeg || extIsTiff || extIsPng)) { + // extension is either empty or unfamiliar. + fname += Glib::ustring (".") + sf.format; + } else if ( !(sf.format == "jpg" && extIsJpeg) + && !(sf.format == "tif" && extIsTiff) + && !(sf.format == "png" && extIsPng ) ) { + // create dialog to warn user that the filename may have two extensions on the end. + Glib::ustring msg_ = Glib::ustring ("") + M("GENERAL_WARNING") + ": " + + M("SAVEDLG_WARNFILENAME") + " \"" + Glib::path_get_basename (fname) + + "." + sf.format + "\""; + Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK_CANCEL, true); + if (msgd.run () == Gtk::RESPONSE_OK) + fname += Glib::ustring (".") + sf.format; + else + return; + } + + response (Gtk::RESPONSE_OK); } void SaveAsDialog::cancelPressed () { - fname = ""; - response = Gtk::RESPONSE_CANCEL; - hide (); + fname = fchooser->get_filename(); + response (Gtk::RESPONSE_CANCEL); } void SaveAsDialog::formatChanged (Glib::ustring f) { diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 38508d5ba..1570a95ab 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -34,10 +34,10 @@ class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { Gtk::FileFilter filter_jpg; Gtk::FileFilter filter_tif; Gtk::FileFilter filter_png; - Gtk::RadioButton* immediately; - Gtk::RadioButton* putToQueueHead; - Gtk::RadioButton* putToQueueTail; - Gtk::ResponseType response; + Gtk::RadioButton* saveMethod[3]; /* 0 -> immediately + * 1 -> putToQueueHead + * 2 -> putToQueueTail + */ public: SaveAsDialog (Glib::ustring initialDir); @@ -49,9 +49,9 @@ class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { bool getImmediately (); bool getToHeadOfQueue (); bool getToTailOfQueue (); + int getSaveMethodNum (); void setInitialFileName (Glib::ustring iname); - Gtk::ResponseType getResponse () { return response; }; void okPressed (); void cancelPressed ();