diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 8806f0f11..b1c58da85 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -712,3 +712,13 @@ HISTOGRAM_BUTTON_L;L ### CURVEEDITOR_NURBS;Control cage + +### + +MAIN_BUTTON_SAVE_TOOLTIP;Save current image Ctrl+S +MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Add current image to processing queue Ctrl+Q +MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Edit current image in external editor Ctrl+E + +### + +SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index cfa30f8d8..059aaa914 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -721,3 +721,6 @@ MAIN_BUTTON_SAVE_TOOLTIP;Save current image Ctrl+S MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Add current image to processing queue Ctrl+Q MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Edit current image in external editor Ctrl+E +### + +SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 07d2f5b4a..0becaf548 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -723,3 +723,6 @@ MAIN_BUTTON_SAVE_TOOLTIP;Enregistrer l'image courante Ctrl+S MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Ajouter l'image courante à la file de traitement Ctrl+Q MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Éditer l'image courante dans l'éditeur externe Ctrl+E +### + +SAVEDLG_AUTOSUFFIX;Ajouter automatiquement un suffixe si le fichier existe déjà diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 9a934c85f..8cfed601d 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -6099,7 +6099,7 @@ void CLASS adobe_coeff (const char *make, const char *model) { "Canon EOS", 0, 0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon PowerShot A530", 0, 0, - { 0 } }, /* don't want the A5 matrix */ + { 0 } }, /* don't want the A5 matrix */ { "Canon PowerShot A50", 0, 0, { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, { "Canon PowerShot A5", 0, 0, @@ -8937,7 +8937,7 @@ dcrMutex->lock (); ifname = fname;//strdup (fname); image = NULL; - + exif_base = -1; ciff_base = -1; ciff_len = -1; @@ -9012,23 +9012,23 @@ dcrMutex->lock (); if (filters) { ri->allocation = (short unsigned int*)calloc(height*width, sizeof(unsigned short)); ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*)); - for (int i=0; idata[i] = ri->allocation + i*width; - for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) if (ISGREEN(ri,row,col)) ri->data[row][col] = image[row*width+col][1]; else if (ISRED(ri,row,col)) ri->data[row][col] = image[row*width+col][0]; - else + else ri->data[row][col] = image[row*width+col][2]; } else { ri->allocation = (short unsigned int*)calloc(3*height*width, sizeof(unsigned short)); ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*)); - for (int i=0; idata[i] = ri->allocation + 3*i*width; - for (int row = 0; row < height; row++) + for (int row = 0; row < height; row++) for (int col = 0; col < width; col++) { ri->data[row][3*col+0] = image[row*width+col][0]; ri->data[row][3*col+1] = image[row*width+col][1]; @@ -9079,7 +9079,7 @@ dcrMutex->lock (); exif_base = -1; ciff_base = -1; ciff_len = -1; - + half_size = 1; bright = 1.0; verbose = settings->verbose; @@ -9165,8 +9165,8 @@ t1.set (); fclose (ifp); dcrMutex->unlock (); return NULL; - } - + } + use_camera_wb = 0; highlight = 1; half_size = 0; @@ -9180,7 +9180,7 @@ t1.set (); } t2.set(); - + iheight = ::height; iwidth = ::width; @@ -9193,7 +9193,7 @@ t2.set(); if (zero_is_bad) remove_zeroes(); rtengine::Thumbnail* tpp = new rtengine::Thumbnail; - + tpp->isRaw = true; tpp->embProfileLength = 0; if (profile_length) { @@ -9207,12 +9207,12 @@ t2.set(); tpp->embProfile = NULL; tpp->embProfileData = NULL; } - + fclose(ifp); tpp->redMultiplier = pre_mul[0]; tpp->greenMultiplier = pre_mul[1]; tpp->blueMultiplier = pre_mul[2]; - + t3.set (); scale_colors(); @@ -9221,13 +9221,13 @@ t3.set (); unsigned filter = filters; int firstgreen = 1; // locate first green location in the first row - while (!FISGREEN(filter,1,firstgreen)) + while (!FISGREEN(filter,1,firstgreen)) firstgreen++; int skip = 1; if (fixwh==1) // fix height, scale width skip = (::height-firstgreen-1) / h; - else + else skip = (::width-firstgreen-1) / w; if (skip%2) skip--; @@ -9237,7 +9237,7 @@ t3.set (); int hskip = skip, vskip = skip; if (!strcmp (model, "D1X")) hskip *=2; - + rml.exifBase = exif_base; rml.ciffBase = ciff_base; rml.ciffLength = ciff_len; @@ -9245,7 +9245,7 @@ t3.set (); tpp->camwbGreen = tpp->greenMultiplier / pre_mul[1]; tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; - tpp->defGain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); + tpp->defGain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); tpp->gammaCorrected = true; int ix = 0; @@ -9272,7 +9272,7 @@ t3.set (); tmpImg->g[y][x] = g; tmpImg->b[y][x] = b; } - } + } } else { for (int row=1, y=0; row< ::height-1 && yg[y][x] = image[ofs][1]; tmpImg->b[y][x] = image[ofs][2]; } - } + } } - + if (fuji_width) { int fw = fuji_width / hskip; double step = sqrt(0.5); @@ -9298,7 +9298,7 @@ t3.set (); for (int col=0; col < wide; col++) { unsigned ur = r = fw + (row-col)*step; unsigned uc = c = (row+col)*step; - if (ur > tmph-2 || uc > tmpw-2) + if (ur > tmph-2 || uc > tmpw-2) continue; double fr = r - ur; double fc = c - uc; @@ -9311,22 +9311,22 @@ t3.set (); delete tmpImg; tmpImg = fImg; } - - + + if (fixwh==1) // fix height, scale width w = tmpw * h / tmph; else h = tmph * w / tmpw; - + tpp->thumbImg = tmpImg->resize (w, h, TI_Bilinear); delete tmpImg; if (fuji_width) tpp->scale = (double)(::height - fuji_width) / sqrt(0.5) / h; else - tpp->scale = (double)::height / h; - -t4.set (); + tpp->scale = (double)::height / h; + +t4.set (); // generate histogram for auto exposure tpp->aeHistCompression = 3; @@ -9348,7 +9348,7 @@ t4.set (); start = 8; end = ::width-8; } - for (int j=start; jaeHistogram[image[i* ::width+j][1]>>tpp->aeHistCompression]+=gadd; else if (FISRED(filter,i,j)) @@ -9356,7 +9356,7 @@ t4.set (); else if (FISBLUE(filter,i,j)) tpp->aeHistogram[image[i* ::width+j][2]>>tpp->aeHistCompression]+=badd; } - + t5.set (); // generate autoWB @@ -9376,7 +9376,7 @@ t5.set (); start = 32; end = ::width-32; } - for (int j=start; jdefGain * image[i* ::width+j][1]; if (d>64000) @@ -9404,7 +9404,7 @@ t5.set (); double reds = pow (avg_r/rn, 1.0/6.0) * tpp->camwbRed; double greens = pow (avg_g/gn, 1.0/6.0) * tpp->camwbGreen; double blues = pow (avg_b/bn, 1.0/6.0) * tpp->camwbBlue; - + double rm = rgb_cam[0][0]*reds + rgb_cam[0][1]*greens + rgb_cam[0][2]*blues; double gm = rgb_cam[1][0]*reds + rgb_cam[1][1]*greens + rgb_cam[1][2]*blues; double bm = rgb_cam[2][0]*reds + rgb_cam[2][1]*greens + rgb_cam[2][2]*blues; @@ -9413,7 +9413,7 @@ t5.set (); t6.set (); -if (settings->verbose) printf ("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d All: %d\n", t1.etime(t0), t2.etime(t1), t3.etime(t2), t4.etime(t3), t5.etime(t4), t6.etime(t5), t6.etime(t0)); +if (settings->verbose) printf ("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d All: %d\n", t1.etime(t0), t2.etime(t1), t3.etime(t2), t4.etime(t3), t5.etime(t4), t6.etime(t5), t6.etime(t0)); int deg = 0; if (flip==5) @@ -9434,7 +9434,7 @@ if (settings->verbose) printf ("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d All: %d tpp->colorMatrix[a][b] = rgb_cam[a][b]; tpp->init (); - + free (image); dcrMutex->unlock (); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index d9458024a..e79fefb5f 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -201,7 +201,16 @@ void ImProcCoordinator::updatePreviewImage (int todo) { progress ("Conversion to RGB...",100*readyphase/numofphases); if (todo!=CROP) { previmg->getMutex().lock(); - ipf.lab2rgb (nprevl, previmg); + try + { + ipf.lab2rgb (nprevl, previmg); + } + catch(char * str) + { + progress ("Error converting file...",0); + mProcessing.unlock (); + return; + } previmg->getMutex().unlock(); } if (!resultValid) { diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 659d839a2..c03c346f4 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -38,6 +38,9 @@ extern const Settings* settings; void ImProcFunctions::lab2rgb (LabImage* lab, Image8* image) { + if (chroma_scale == 0) + throw "Division by zero exception"; + if (monitorTransform) { int ix = 0; short* buffer = new short [3*lab->W]; diff --git a/rtengine/loadinitial.cc.orig b/rtengine/loadinitial.cc.orig new file mode 100644 index 000000000..308005e30 --- /dev/null +++ b/rtengine/loadinitial.cc.orig @@ -0,0 +1,43 @@ +/* + * 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 +#include +#include + +namespace rtengine { + +InitialImage* InitialImage::load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl) { + + ImageSource* isrc; + + if (!isRaw) + isrc = new StdImageSource (); + else + isrc = new RawImageSource (); + + isrc->setProgressListener (pl); + *errorCode = isrc->load (fname); + if (*errorCode) { + delete isrc; + return NULL; + } + return isrc; +} +} + diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index b64238e3b..8ac174d4f 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -222,7 +222,7 @@ void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) { void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) { if (bpl) - Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, false, true, Glib::THREAD_PRIORITY_NORMAL); + Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, false, true, Glib::THREAD_PRIORITY_LOW); } } diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 61713d845..c2999933c 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -197,14 +197,17 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { if (img && fname!="") { int err = 0; if (saveFormat.format=="tif") - err = img->saveAsTIFF (fname, saveFormat.tiffBits); + err = img->saveAsTIFF (fname, saveFormat.tiffBits,saveFormat.tiffUncompressed); else if (saveFormat.format=="png") err = img->saveAsPNG (fname, saveFormat.pngCompression, saveFormat.pngBits); else if (saveFormat.format=="jpg") err = img->saveAsJPEG (fname, saveFormat.jpegQuality); img->free (); if (!err && saveFormat.saveParams) - processing->params.save (removeExtension(fname) + paramFileExtension); + // We keep the extension to avoid overwriting the profile when we have + // the same output filename with different extension + //processing->params.save (removeExtension(fname) + paramFileExtension); + processing->params.save (fname + paramFileExtension); if (processing->thumbnail) { processing->thumbnail->imageDeveloped (); processing->thumbnail->imageRemovedFromQueue (); diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index f98cab189..2f4a42170 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -59,7 +59,7 @@ void BatchQueueEntryUpdater::process () { if (stopped) #undef THREAD_PRIORITY_NORMAL - thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); + thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); } void BatchQueueEntryUpdater::process_ () { diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 16b4d6172..7d6ae81d7 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1,961 +1,961 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include - -using namespace rtengine::procparams; - -EditorPanel::EditorPanel (FilePanel* filePanel) : beforePreviewHandler(NULL), beforeIarea(NULL), parent(NULL), beforeIpc(NULL) { - - epih = new EditorPanelIdleHelper; - epih->epanel = this; - epih->destroyed = false; - epih->pending = 0; - -// construct toolpanelcoordinator - tpc = new ToolPanelCoordinator (); - -// build GUI - // build left side panel - leftbox = new Gtk::VBox (); - leftbox->set_border_width (4); - - histogramPanel = Gtk::manage (new HistogramPanel ()); - histogramPanel->set_size_request (-1, 150); -// leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); - - profilep = Gtk::manage (new ProfilePanel ()); - Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ()); - ppframe->add (*profilep); - ppframe->set_label (M("PROFILEPANEL_LABEL")); -// leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); - - navigator = Gtk::manage (new Navigator ()); - navigator->previewWindow->set_size_request (-1, 150); - leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4); - - history = Gtk::manage (new History ()); - leftbox->pack_start (*history); - - leftbox->show_all (); - - // build the middle of the screen - Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ()); - - info = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (argv0+"/images/info.png")); - info->add (*infoimg); - info->set_relief(Gtk::RELIEF_NONE); - info->set_tooltip_markup (M("MAIN_TOOLTIP_QINFO")); - - beforeAfter = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* beforeAfterIcon = Gtk::manage (new Gtk::Image (argv0+"/images/beforeafter.png")); - beforeAfter->add(*beforeAfterIcon); - beforeAfter->set_relief(Gtk::RELIEF_NONE); - beforeAfter->set_tooltip_markup (M("MAIN_TOOLTIP_TOGGLE")); - - - Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ()); - - hidehp = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ()); - hidehpLabel->set_markup ("H"); - Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (argv0+"/images/left.png")); - Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ()); - hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2); - hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2); - hidehp->add (*hidehpBox); - hidehp->set_relief(Gtk::RELIEF_NONE); - hidehp->set_active (options.showHistory); - hidehp->set_tooltip_markup (M("MAIN_TOOLTIP_HIDEHP")); - - Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ()); - - iarea = new ImageAreaPanel (); - - Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); - toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1); - toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2); - toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4); - toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4); - toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0); - toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2); - - afterBox = Gtk::manage (new Gtk::VBox ()); - afterBox->pack_start (*iarea); - - beforeAfterBox = Gtk::manage (new Gtk::HBox()); - beforeAfterBox->pack_start (*afterBox); - - editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK); - editbox->pack_start (*beforeAfterBox); - - // build right side panel - vboxright = new Gtk::VBox (false, 0); - vboxright->set_border_width (4); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); - vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); - // main notebook - vboxright->pack_start (*tpc->toolPanelNotebook); - - // Save buttons - Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ()); - - Gtk::HBox * saveButtonBox = Gtk::manage(new Gtk::HBox()); - saveButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); - saveButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SAVE"))), Gtk::PACK_SHRINK, 2); - saveimgas = Gtk::manage (new Gtk::Button ()); - saveimgas->add(*saveButtonBox); - saveimgas->set_tooltip_markup(M("MAIN_BUTTON_SAVE_TOOLTIP")); - - Gtk::HBox * queueButtonBox = Gtk::manage(new Gtk::HBox()); - queueButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); - queueButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_PUTTOQUEUE"))), Gtk::PACK_SHRINK, 2); - queueimg = Gtk::manage (new Gtk::Button ()); - queueimg->add(*queueButtonBox); - queueimg->set_tooltip_markup(M("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP")); - - Gtk::HBox * sendToEditorButtonBox = Gtk::manage(new Gtk::HBox()); - sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Image (argv0+"/images/gimp.png")), Gtk::PACK_SHRINK, 2); - sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SENDTOEDITOR"))), Gtk::PACK_SHRINK, 2); - sendtogimp = Gtk::manage (new Gtk::Button ()); - sendtogimp->add(*sendToEditorButtonBox); - sendtogimp->set_tooltip_markup(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP")); - - iops->pack_start (*saveimgas, Gtk::PACK_SHRINK); - iops->pack_start (*queueimg, Gtk::PACK_SHRINK); - iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK); - - // Status box - statusBox = Gtk::manage (new Gtk::HBox ()); - progressLabel = Gtk::manage (new Gtk::Label("")); - statusBox->pack_start (*progressLabel); - red = new Gtk::Image (argv0+"/images/red.png"); - green = new Gtk::Image (argv0+"/images/green.png"); - red->show (); - green->show (); - statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); - iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4); - - // Zoom panel - iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); - iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2); - - - editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4); - editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4); - editbox->show_all (); - - // build screen - hpanedl = Gtk::manage (new Gtk::HPaned()); - hpanedr = Gtk::manage (new Gtk::HPaned()); - leftbox->reference (); - vboxright->reference (); - if (options.showHistory) { - hpanedl->pack1(*leftbox, false, true); - hpanedl->set_position (options.historyPanelWidth); - } - - ipc = NULL; - btpCoordinator = new BatchToolPanelCoordinator (filePanel); - fCatalog = new FileCatalog (btpCoordinator->coarse, btpCoordinator->getToolBar()); //, filePanel->fileCatalog->fileBrowser); - filePanel->dirBrowser->addDirSelectionListener (fCatalog); - // fCatalog->setFilterPanel (filePanel->filterPanel); - fCatalog->setImageAreaToolListener (btpCoordinator); - fCatalog->setFileSelectionListener (filePanel); - fCatalog->setFileSelectionChangeListener (btpCoordinator); - fCatalog->setEnabled(true); - - Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned()); - viewpaned->pack1(*fCatalog, false, true); - viewpaned->pack2(*editbox, true, true); - - Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); - vbfr->add (*viewpaned); - hpanedl->pack2(*vbfr, true, true); - - hpanedr->pack1(*hpanedl, true, true); - hpanedr->pack2(*vboxright, false, true); - - pack_start (*hpanedr); - show_all (); - - // save as dialog - if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) - saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); - else - saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES)); - - saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); - -// connect listeners - profilep->setProfileChangeListener (tpc); - history->setProfileChangeListener (tpc); - history->setHistoryBeforeLineListener (this); - tpc->addPParamsChangeListener (profilep); - tpc->addPParamsChangeListener (history); - tpc->addPParamsChangeListener (this); - iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener()); - iarea->imageArea->setPointerMotionListener (navigator); - iarea->imageArea->setImageAreaToolListener (tpc); - -// initialize components - info->set_active (options.showInfo); - tpc->readOptions (); - -// connect event handlers - info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) ); - beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) ); - hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) ); - saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) ); - queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) ); - sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) ); - -} - -bool EditorPanel::beforeClosing () { - - options.toolPanelWidth = vboxright->get_width (); - return true; -} - -EditorPanel::~EditorPanel () { - - history->setHistoryBeforeLineListener (NULL); - // the order is important! - delete iarea; - delete beforeIarea; - - if (ipc) - ipc->setPreviewImageListener (NULL); - if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); - - delete previewHandler; - delete beforePreviewHandler; - - if (ipc) - close (); - - if (epih->pending) - epih->destroyed = true; - else - delete epih; - - delete tpc; - - delete red; - delete green; - delete leftbox; - delete vboxright; - - delete saveAsDialog; -} - -void EditorPanel::on_realize () { - - Gtk::VBox::on_realize (); - vboxright->set_size_request (options.toolPanelWidth, -1); -} - -void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { - - if (ipc) close(); - // initialize everything - openThm = tmb; - openThm->increaseRef (); - - previewHandler = new PreviewHandler (); - - this->isrc = isrc; - ipc = rtengine::StagedImageProcessor::create (isrc); - ipc->setProgressListener (this); - ipc->setPreviewImageListener (previewHandler); - ipc->setPreviewScale (10); - tpc->initImage (ipc, tmb->getType()==FT_Raw); - ipc->setHistogramListener (this); - -// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen - iarea->imageArea->setPreviewHandler (previewHandler); - iarea->imageArea->setImProcCoordinator (ipc); - navigator->previewWindow->setPreviewHandler (previewHandler); - navigator->previewWindow->setImageArea (iarea->imageArea); - - // try to load the last saved parameters from the cache or from the paramfile file - ProcParams* ldprof = NULL; - if (openThm->hasProcParams()) { - ldprof = new ProcParams (); - *ldprof = openThm->getProcParams (); - } - - // initialize profile - if (openThm->getType()!=FT_Raw) - profilep->initProfile (options.defProfImg, ldprof, NULL); - else - profilep->initProfile (options.defProfRaw, ldprof, NULL); - - openThm->addThumbnailListener (this); - info_toggled (); - - if (beforeIarea) - { - beforeAfterToggled(); - beforeAfterToggled(); - } - - Gtk::Allocation r; - iarea->imageArea->on_resized(r); - //iarea->show_all(); - //hpanedl->show_all(); - //show_all(); - -} - -void EditorPanel::close () { - - if (ipc) - { - saveProfile (); - // close image processor and the current thumbnail - tpc->closeImage (); // this call stops image processing - tpc->writeOptions (); - - if (ipc) - ipc->setPreviewImageListener (NULL); - - if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); - - delete previewHandler; - previewHandler= NULL; -// delete beforePreviewHandler; -// beforePreviewHandler = NULL; - - delete iarea->imageArea->mainCropWindow; - iarea->imageArea->mainCropWindow = NULL; - - rtengine::StagedImageProcessor::destroy (ipc); - ipc = NULL; - - iarea->imageArea->setPreviewHandler (NULL); - iarea->imageArea->setImProcCoordinator (NULL); - navigator->previewWindow->setPreviewHandler (NULL); - // navigator->previewWindow->setImageArea (NULL); - - openThm->removeThumbnailListener (this); - openThm->decreaseRef (); - - - } -} - -void EditorPanel::saveProfile () { - - ProcParams params; - ipc->getParams (¶ms); - - if (options.saveParamsFile) - params.save (openThm->getFileName() + paramFileExtension); - if (openThm && options.saveParamsCache) - openThm->setProcParams (params, EDITOR); -} - -Glib::ustring EditorPanel::getShortName () { - - return Glib::path_get_basename (openThm->getFileName ()); -} - -Glib::ustring EditorPanel::getFileName () { - - return openThm->getFileName (); -} - -// TODO!!! -void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { - -// if (ev!=EvPhotoLoaded) -// saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); -} - -struct spsparams { - bool state; - EditorPanelIdleHelper* epih; -}; - -int setprocstate (void* data) { - - gdk_threads_enter (); - spsparams* p = (spsparams*)data; - - if (p->epih->destroyed) { - if (p->epih->pending == 1) - delete p->epih; - else - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; - } - - p->epih->epanel->refreshProcessingState (p->state); - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; -} - -void EditorPanel::setProgressState (int state) { - - epih->pending++; - - spsparams* p = new spsparams; - p->state = state; - p->epih = epih; - g_idle_add (setprocstate, p); -} - -void EditorPanel::refreshProcessingState (bool state) { - - // Set proc params of thumbnail. It saves it into the cache and updates the file browser. - if (ipc && openThm && !state && tpc->getChangedState()) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - openThm->setProcParams (pparams, EDITOR, false); - } - - // change state of the led - std::vector children = (std::vector) statusBox->get_children(); - if (children.size()>=1) { - Gtk::Widget* wlast = children[children.size()-1]; - if (wlast) - statusBox->remove (*wlast); - } - if (state) - statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4); - else - statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); -} - -struct errparams { - Glib::ustring descr; - EditorPanelIdleHelper* epih; -}; - -void EditorPanel::displayError (Glib::ustring descr) { - - if (parent) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_title (M("MAIN_MSG_CANNOTSAVE")); - msgd->run (); - delete msgd; - } -} - -int disperror (void* data) { - - gdk_threads_enter (); - errparams* p = (errparams*)data; - - if (p->epih->destroyed) { - if (p->epih->pending == 1) - delete p->epih; - else - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; - } - - p->epih->epanel->displayError (p->descr); - p->epih->pending--; - delete p; - gdk_threads_leave (); - return 0; -} - -void EditorPanel::error (Glib::ustring descr) { - - epih->pending++; - errparams* p = new errparams; - p->descr = descr; - p->epih = epih; - g_idle_add (disperror, p); -} - -void EditorPanel::info_toggled () { - - Glib::ustring infoString; - - const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); - if (idata && idata->hasExif()) - infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n", - Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()), - Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), - M("QINFO_ISO"), idata->getISOSpeed(), - M("QINFO_FOCALLENGTH"), idata->getFocalLen()) - + Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens())); - else - infoString = M("QINFO_NOEXIF"); - - iarea->imageArea->setInfoText (infoString); - iarea->imageArea->infoEnabled (info->get_active ()); -} - -void EditorPanel::hideHistoryActivated () { - - removeIfThere (hpanedl, leftbox, false); - if (hidehp->get_active()) - hpanedl->pack1 (*leftbox, false, true); - options.showHistory = hidehp->get_active(); -} - -bool EditorPanel::handleShortcutKey (GdkEventKey* event) { - - bool ctrl = event->state & GDK_CONTROL_MASK; - bool shift = event->state & GDK_SHIFT_MASK; - - if (!ctrl) { - switch(event->keyval) { - case GDK_h: - case GDK_H: - hidehp->set_active (!hidehp->get_active()); - return true; - case GDK_w: - case GDK_W: - tpc->getToolBar()->wb_pressed (); - return true; - case GDK_c: - case GDK_C: - tpc->getToolBar()->crop_pressed (); - return true; - case GDK_s: - case GDK_S: - tpc->getToolBar()->stra_pressed (); - return true; - case GDK_n: - case GDK_N: - tpc->getToolBar()->hand_pressed (); - return true; - case GDK_i: - case GDK_I: - info->set_active (!info->get_active()); - return true; - case GDK_b: - case GDK_B: - beforeAfter->set_active (!beforeAfter->get_active()); - return true; - case GDK_plus: - case GDK_equal: - iarea->imageArea->zoomPanel->zoomInClicked(); - return true; - case GDK_minus: - case GDK_underscore: - iarea->imageArea->zoomPanel->zoomOutClicked(); - return true; - case GDK_1: - iarea->imageArea->zoomPanel->zoom11Clicked(); - return true; - case GDK_f: - case GDK_F: - iarea->imageArea->zoomPanel->zoomFitClicked(); - return true; - } - } - else { - switch (event->keyval) { - case GDK_s: - saveAsPressed(); - return true; - case GDK_q: - queueImgPressed(); - return true; - case GDK_e: - sendToGimpPressed(); - return true; - case GDK_z: - history->undo (); - return true; - case GDK_Z: - history->redo (); - return true; - } - } - - return false; -} - -void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { - - if (whoChangedIt!=EDITOR) - tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, M("PROGRESSDLG_PROFILECHANGEDINBROWSER")); -} - -bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, bool findNewNameIfNeeded){ - rtengine::IImage16* img = pc->returnValue(); - delete pc; - if( img ) - saveImage( img, fname, sf, findNewNameIfNeeded); - else{ - Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - - } - return false; -} - -BatchQueueEntry* EditorPanel::createBatchQueueEntry () { - - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - int prevh = options.maxThumbnailHeight; - int prevw = prevh; - guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh); - double tmpscale; - rtengine::IImage8* img = openThm->processThumbImage (pparams, options.maxThumbnailHeight, tmpscale); - if (img) { - prevw = img->getWidth (); - prevh = img->getHeight (); - prev = new guint8 [prevw*prevh*3]; - memcpy (prev, img->getData (), prevw*prevh*3); - img->free(); - } - return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm); -} - -int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) { - - Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); - if (findNewNameIfNeeded) { - int tries = 1; - while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { - fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); - tries++; - } - if (tries==1000) - return -1000; - } - ProgressConnector *ld = new ProgressConnector(); - img->setSaveProgressListener (parent->getProgressListener()); - if (sf.format=="tif") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - else if (sf.format=="png") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - else if (sf.format=="jpg") - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); - return 0; -} - -bool EditorPanel::idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf){ - img->free (); - if (! pc->returnValue() ) { - openThm->imageDeveloped (); - // save processing parameters, if needed - if (sf.saveParams) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - pparams.save (removeExtension (fname) + ".out" + paramFileExtension); - } - }else{ - Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image saving\n"; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - } - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); - delete pc; - return false; -} - -void EditorPanel::saveAsPressed () { - - // obtaining short name without extension - saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName()))); - saveAsDialog->run (); - Glib::ustring fname = saveAsDialog->getFileName (); - if (fname=="") - return; - - options.lastSaveAsPath = saveAsDialog->getDirectory (); - options.saveAsDialogWidth = saveAsDialog->get_width(); - options.saveAsDialogHeight = saveAsDialog->get_height(); - - SaveFormat sf = saveAsDialog->getFormat (); - if (getExtension (fname)!=sf.format) - fname = fname + "." + sf.format; - - options.saveFormat = sf; - - if (saveAsDialog->getImmediately ()) { - // check if it exists - if (Glib::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 (); - if (response==Gtk::RESPONSE_NO) - return; - } - // save image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - fname = removeExtension (fname); - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fname,sf,false )); - saveimgas->set_sensitive(false); - sendtogimp->set_sensitive(false); - } - else { - BatchQueueEntry* bqe = createBatchQueueEntry (); - bqe->outFileName = fname; - bqe->saveFormat = saveAsDialog->getFormat (); - parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); - } - // ask parent to redraw file browser - // ... or does it automatically when the tab is switched to it -} - -void EditorPanel::queueImgPressed () { - - saveProfile (); - parent->addBatchQueueJob (createBatchQueueEntry ()); -} - -void EditorPanel::sendToGimpPressed () { - // develop image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_sendToGimp ),ld )); - saveimgas->set_sensitive(false); - sendtogimp->set_sensitive(false); -} - -bool EditorPanel::idle_sendToGimp( ProgressConnector *pc){ - - rtengine::IImage16* img = pc->returnValue(); - delete pc; - if (img) { - // get file name base - Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName())); - Glib::ustring dirname = Glib::get_tmp_dir (); - Glib::ustring fname = Glib::build_filename (dirname, shortname); - - SaveFormat sf; - sf.format = "tif"; - sf.tiffBits = 16; - - Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); - - int tries = 1; - while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { - fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); - tries++; - } - if (tries==1000){ - img->free (); - return false; - } - - ProgressConnector *ld = new ProgressConnector(); - img->setSaveProgressListener (parent->getProgressListener()); - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_sentToGimp), ld, img, fileName)); - }else{ - Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - } - return false; -} - -bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename){ - img->free (); - int errore = pc->returnValue(); - delete pc; - if (!errore) { - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); - bool success=false; - Glib::ustring cmdLine; - // start gimp - if (options.editorToSendTo==1) { -#ifdef _WIN32 - cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\""; -#else - cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - if (!success){ -#ifdef _WIN32 - int ver = 12; - while (!success && ver) { - cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\""; - ver--; - success = safe_spawn_command_line_async (cmdLine); - } -#elif defined __APPLE__ - cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; - success = safe_spawn_command_line_async (cmdLine); -#else - cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; - success = safe_spawn_command_line_async (cmdLine); -#endif - } - } - else if (options.editorToSendTo==2) { -#ifdef __APPLE__ - cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir,"Photoshop.app\' ") + "\'" + filename + "\'"; -#else - cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - } - else if (options.editorToSendTo==3) { -#ifdef __APPLE__ - cmdLine = Glib::ustring("") + options.customEditorProg + filename; -#else - cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\""; -#endif - success = safe_spawn_command_line_async (cmdLine); - } - - if (!success) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); - msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR")); - msgd->run (); - delete msgd; - } - - } - - return false; -} - -void EditorPanel::saveOptions () { - - close(); - options.historyPanelWidth = hpanedl->get_position (); - options.toolPanelWidth = vboxright->get_width (); - if (options.startupDir==STARTUPDIR_LAST && fCatalog->lastSelectedDir ()!="") - options.startupPath = fCatalog->lastSelectedDir (); - fCatalog->closeDir (); -} - -void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { - - if (beforeIpc) { - ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged); - *pparams = params; - beforeIpc->paramsUpdateReady (); - } -} - -void EditorPanel::beforeAfterToggled () { - - removeIfThere (beforeAfterBox, beforeBox, false); - removeIfThere (afterBox, afterLabel, false); - - if (beforeIarea) { - if (beforeIpc) - beforeIpc->stopProcessing (); - iarea->setBeforeAfterViews (NULL, iarea); - delete beforeIarea; - beforeIarea = NULL; - if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); - delete beforePreviewHandler; - beforePreviewHandler = NULL; - if (beforeIpc) - rtengine::StagedImageProcessor::destroy (beforeIpc); - beforeIpc = NULL; - } - - if (beforeAfter->get_active ()) { - - beforeIarea = new ImageAreaPanel (); - - beforeLabel = Gtk::manage (new Gtk::Label ()); - beforeLabel->set_markup (Glib::ustring("") + M("GENERAL_BEFORE") + ""); - beforeBox = Gtk::manage (new Gtk::VBox ()); - beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2); - beforeBox->pack_start (*beforeIarea); - - afterLabel = Gtk::manage (new Gtk::Label ()); - afterLabel->set_markup (Glib::ustring("") + M("GENERAL_AFTER") + ""); - afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2); - afterBox->reorder_child (*afterLabel, 0); - - beforeAfterBox->pack_start (*beforeBox); - beforeAfterBox->reorder_child (*beforeBox, 0); - beforeAfterBox->show_all (); - - beforePreviewHandler = new PreviewHandler (); - isrc->increaseRef (); - beforeIpc = rtengine::StagedImageProcessor::create (isrc); - beforeIpc->setPreviewScale (10); - beforeIpc->setPreviewImageListener (beforePreviewHandler); - beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler); - beforeIarea->imageArea->setImProcCoordinator (beforeIpc); - - iarea->setBeforeAfterViews (beforeIarea, iarea); - beforeIarea->setBeforeAfterViews (beforeIarea, iarea); - - rtengine::procparams::ProcParams params; - if (history->getBeforeLineParams (params)) - historyBeforeLineChanged (params); - } -} - -void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) { - - histogramPanel->histogramChanged (rh, gh, bh, lh); - tpc->updateCurveBackgroundHistogram (bcrgb, bcl); -} +/* + * 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 +#include +#include +#include +#include +#include +#include + +using namespace rtengine::procparams; + +EditorPanel::EditorPanel (FilePanel* filePanel) : beforePreviewHandler(NULL), beforeIarea(NULL), parent(NULL), beforeIpc(NULL) { + + epih = new EditorPanelIdleHelper; + epih->epanel = this; + epih->destroyed = false; + epih->pending = 0; + +// construct toolpanelcoordinator + tpc = new ToolPanelCoordinator (); + +// build GUI + // build left side panel + leftbox = new Gtk::VBox (); + leftbox->set_border_width (4); + + histogramPanel = Gtk::manage (new HistogramPanel ()); + histogramPanel->set_size_request (-1, 150); +// leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); + + profilep = Gtk::manage (new ProfilePanel ()); + Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ()); + ppframe->add (*profilep); + ppframe->set_label (M("PROFILEPANEL_LABEL")); +// leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); + + navigator = Gtk::manage (new Navigator ()); + navigator->previewWindow->set_size_request (-1, 150); + leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4); + + history = Gtk::manage (new History ()); + leftbox->pack_start (*history); + + leftbox->show_all (); + + // build the middle of the screen + Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ()); + + info = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (argv0+"/images/info.png")); + info->add (*infoimg); + info->set_relief(Gtk::RELIEF_NONE); + info->set_tooltip_markup (M("MAIN_TOOLTIP_QINFO")); + + beforeAfter = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* beforeAfterIcon = Gtk::manage (new Gtk::Image (argv0+"/images/beforeafter.png")); + beforeAfter->add(*beforeAfterIcon); + beforeAfter->set_relief(Gtk::RELIEF_NONE); + beforeAfter->set_tooltip_markup (M("MAIN_TOOLTIP_TOGGLE")); + + + Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ()); + + hidehp = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ()); + hidehpLabel->set_markup ("H"); + Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (argv0+"/images/left.png")); + Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ()); + hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2); + hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2); + hidehp->add (*hidehpBox); + hidehp->set_relief(Gtk::RELIEF_NONE); + hidehp->set_active (options.showHistory); + hidehp->set_tooltip_markup (M("MAIN_TOOLTIP_HIDEHP")); + + Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ()); + Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ()); + + iarea = new ImageAreaPanel (); + + Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); + toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1); + toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2); + toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4); + toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4); + toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0); + toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2); + + afterBox = Gtk::manage (new Gtk::VBox ()); + afterBox->pack_start (*iarea); + + beforeAfterBox = Gtk::manage (new Gtk::HBox()); + beforeAfterBox->pack_start (*afterBox); + + editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK); + editbox->pack_start (*beforeAfterBox); + + // build right side panel + vboxright = new Gtk::VBox (false, 0); + vboxright->set_border_width (4); + vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4); + vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); + // main notebook + vboxright->pack_start (*tpc->toolPanelNotebook); + + // Save buttons + Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ()); + + Gtk::HBox * saveButtonBox = Gtk::manage(new Gtk::HBox()); + saveButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); + saveButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SAVE"))), Gtk::PACK_SHRINK, 2); + saveimgas = Gtk::manage (new Gtk::Button ()); + saveimgas->add(*saveButtonBox); + saveimgas->set_tooltip_markup(M("MAIN_BUTTON_SAVE_TOOLTIP")); + + Gtk::HBox * queueButtonBox = Gtk::manage(new Gtk::HBox()); + queueButtonBox->pack_start(*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)), Gtk::PACK_SHRINK, 2); + queueButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_PUTTOQUEUE"))), Gtk::PACK_SHRINK, 2); + queueimg = Gtk::manage (new Gtk::Button ()); + queueimg->add(*queueButtonBox); + queueimg->set_tooltip_markup(M("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP")); + + Gtk::HBox * sendToEditorButtonBox = Gtk::manage(new Gtk::HBox()); + sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Image (argv0+"/images/gimp.png")), Gtk::PACK_SHRINK, 2); + sendToEditorButtonBox->pack_start(*Gtk::manage (new Gtk::Label (M("MAIN_BUTTON_SENDTOEDITOR"))), Gtk::PACK_SHRINK, 2); + sendtogimp = Gtk::manage (new Gtk::Button ()); + sendtogimp->add(*sendToEditorButtonBox); + sendtogimp->set_tooltip_markup(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP")); + + iops->pack_start (*saveimgas, Gtk::PACK_SHRINK); + iops->pack_start (*queueimg, Gtk::PACK_SHRINK); + iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK); + + // Status box + statusBox = Gtk::manage (new Gtk::HBox ()); + progressLabel = Gtk::manage (new Gtk::Label("")); + statusBox->pack_start (*progressLabel); + red = new Gtk::Image (argv0+"/images/red.png"); + green = new Gtk::Image (argv0+"/images/green.png"); + red->show (); + green->show (); + statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); + iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4); + + // Zoom panel + iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); + iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2); + + + editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4); + editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4); + editbox->show_all (); + + // build screen + hpanedl = Gtk::manage (new Gtk::HPaned()); + hpanedr = Gtk::manage (new Gtk::HPaned()); + leftbox->reference (); + vboxright->reference (); + if (options.showHistory) { + hpanedl->pack1(*leftbox, false, true); + hpanedl->set_position (options.historyPanelWidth); + } + + ipc = NULL; + btpCoordinator = new BatchToolPanelCoordinator (filePanel); + fCatalog = new FileCatalog (btpCoordinator->coarse, btpCoordinator->getToolBar()); //, filePanel->fileCatalog->fileBrowser); + filePanel->dirBrowser->addDirSelectionListener (fCatalog); + // fCatalog->setFilterPanel (filePanel->filterPanel); + fCatalog->setImageAreaToolListener (btpCoordinator); + fCatalog->setFileSelectionListener (filePanel); + fCatalog->setFileSelectionChangeListener (btpCoordinator); + fCatalog->setEnabled(true); + + Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned()); + viewpaned->pack1(*fCatalog, false, true); + viewpaned->pack2(*editbox, true, true); + + Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); + vbfr->add (*viewpaned); + hpanedl->pack2(*vbfr, true, true); + + hpanedr->pack1(*hpanedl, true, true); + hpanedr->pack2(*vboxright, false, true); + + pack_start (*hpanedr); + show_all (); + + // save as dialog + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); + else + saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES)); + + saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); + +// connect listeners + profilep->setProfileChangeListener (tpc); + history->setProfileChangeListener (tpc); + history->setHistoryBeforeLineListener (this); + tpc->addPParamsChangeListener (profilep); + tpc->addPParamsChangeListener (history); + tpc->addPParamsChangeListener (this); + iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener()); + iarea->imageArea->setPointerMotionListener (navigator); + iarea->imageArea->setImageAreaToolListener (tpc); + +// initialize components + info->set_active (options.showInfo); + tpc->readOptions (); + +// connect event handlers + info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) ); + beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) ); + hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) ); + saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) ); + queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) ); + sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) ); + +} + +bool EditorPanel::beforeClosing () { + + options.toolPanelWidth = vboxright->get_width (); + return true; +} + +EditorPanel::~EditorPanel () { + + history->setHistoryBeforeLineListener (NULL); + // the order is important! + delete iarea; + delete beforeIarea; + + if (ipc) + ipc->setPreviewImageListener (NULL); + if (beforeIpc) + beforeIpc->setPreviewImageListener (NULL); + + delete previewHandler; + delete beforePreviewHandler; + + if (ipc) + close (); + + if (epih->pending) + epih->destroyed = true; + else + delete epih; + + delete tpc; + + delete red; + delete green; + delete leftbox; + delete vboxright; + + delete saveAsDialog; +} + +void EditorPanel::on_realize () { + + Gtk::VBox::on_realize (); + vboxright->set_size_request (options.toolPanelWidth, -1); +} + +void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { + + if (ipc) close(); + // initialize everything + openThm = tmb; + openThm->increaseRef (); + + previewHandler = new PreviewHandler (); + + this->isrc = isrc; + ipc = rtengine::StagedImageProcessor::create (isrc); + ipc->setProgressListener (this); + ipc->setPreviewImageListener (previewHandler); + ipc->setPreviewScale (10); + tpc->initImage (ipc, tmb->getType()==FT_Raw); + ipc->setHistogramListener (this); + +// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen + iarea->imageArea->setPreviewHandler (previewHandler); + iarea->imageArea->setImProcCoordinator (ipc); + navigator->previewWindow->setPreviewHandler (previewHandler); + navigator->previewWindow->setImageArea (iarea->imageArea); + + // try to load the last saved parameters from the cache or from the paramfile file + ProcParams* ldprof = NULL; + if (openThm->hasProcParams()) { + ldprof = new ProcParams (); + *ldprof = openThm->getProcParams (); + } + + // initialize profile + if (openThm->getType()!=FT_Raw) + profilep->initProfile (options.defProfImg, ldprof, NULL); + else + profilep->initProfile (options.defProfRaw, ldprof, NULL); + + openThm->addThumbnailListener (this); + info_toggled (); + + if (beforeIarea) + { + beforeAfterToggled(); + beforeAfterToggled(); + } + + Gtk::Allocation r; + iarea->imageArea->on_resized(r); + //iarea->show_all(); + //hpanedl->show_all(); + //show_all(); + +} + +void EditorPanel::close () { + + if (ipc) + { + saveProfile (); + // close image processor and the current thumbnail + tpc->closeImage (); // this call stops image processing + tpc->writeOptions (); + + if (ipc) + ipc->setPreviewImageListener (NULL); + + if (beforeIpc) + beforeIpc->setPreviewImageListener (NULL); + + delete previewHandler; + previewHandler= NULL; +// delete beforePreviewHandler; +// beforePreviewHandler = NULL; + + delete iarea->imageArea->mainCropWindow; + iarea->imageArea->mainCropWindow = NULL; + + rtengine::StagedImageProcessor::destroy (ipc); + ipc = NULL; + + iarea->imageArea->setPreviewHandler (NULL); + iarea->imageArea->setImProcCoordinator (NULL); + navigator->previewWindow->setPreviewHandler (NULL); + // navigator->previewWindow->setImageArea (NULL); + + openThm->removeThumbnailListener (this); + openThm->decreaseRef (); + + + } +} + +void EditorPanel::saveProfile () { + + ProcParams params; + ipc->getParams (¶ms); + + if (options.saveParamsFile) + params.save (openThm->getFileName() + paramFileExtension); + if (openThm && options.saveParamsCache) + openThm->setProcParams (params, EDITOR); +} + +Glib::ustring EditorPanel::getShortName () { + + return Glib::path_get_basename (openThm->getFileName ()); +} + +Glib::ustring EditorPanel::getFileName () { + + return openThm->getFileName (); +} + +// TODO!!! +void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { + +// if (ev!=EvPhotoLoaded) +// saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); +} + +struct spsparams { + bool state; + EditorPanelIdleHelper* epih; +}; + +int setprocstate (void* data) { + + gdk_threads_enter (); + spsparams* p = (spsparams*)data; + + if (p->epih->destroyed) { + if (p->epih->pending == 1) + delete p->epih; + else + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; + } + + p->epih->epanel->refreshProcessingState (p->state); + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; +} + +void EditorPanel::setProgressState (int state) { + + epih->pending++; + + spsparams* p = new spsparams; + p->state = state; + p->epih = epih; + g_idle_add (setprocstate, p); +} + +void EditorPanel::refreshProcessingState (bool state) { + + // Set proc params of thumbnail. It saves it into the cache and updates the file browser. + if (ipc && openThm && !state && tpc->getChangedState()) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + openThm->setProcParams (pparams, EDITOR, false); + } + + // change state of the led + std::vector children = (std::vector) statusBox->get_children(); + if (children.size()>=1) { + Gtk::Widget* wlast = children[children.size()-1]; + if (wlast) + statusBox->remove (*wlast); + } + if (state) + statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4); + else + statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4); +} + +struct errparams { + Glib::ustring descr; + EditorPanelIdleHelper* epih; +}; + +void EditorPanel::displayError (Glib::ustring descr) { + + if (parent) { + Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd->set_title (M("MAIN_MSG_CANNOTSAVE")); + msgd->run (); + delete msgd; + } +} + +int disperror (void* data) { + + gdk_threads_enter (); + errparams* p = (errparams*)data; + + if (p->epih->destroyed) { + if (p->epih->pending == 1) + delete p->epih; + else + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; + } + + p->epih->epanel->displayError (p->descr); + p->epih->pending--; + delete p; + gdk_threads_leave (); + return 0; +} + +void EditorPanel::error (Glib::ustring descr) { + + epih->pending++; + errparams* p = new errparams; + p->descr = descr; + p->epih = epih; + g_idle_add (disperror, p); +} + +void EditorPanel::info_toggled () { + + Glib::ustring infoString; + + const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); + if (idata && idata->hasExif()) + infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n", + Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()), + Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), + M("QINFO_ISO"), idata->getISOSpeed(), + M("QINFO_FOCALLENGTH"), idata->getFocalLen()) + + Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens())); + else + infoString = M("QINFO_NOEXIF"); + + iarea->imageArea->setInfoText (infoString); + iarea->imageArea->infoEnabled (info->get_active ()); +} + +void EditorPanel::hideHistoryActivated () { + + removeIfThere (hpanedl, leftbox, false); + if (hidehp->get_active()) + hpanedl->pack1 (*leftbox, false, true); + options.showHistory = hidehp->get_active(); +} + +bool EditorPanel::handleShortcutKey (GdkEventKey* event) { + + bool ctrl = event->state & GDK_CONTROL_MASK; + bool shift = event->state & GDK_SHIFT_MASK; + + if (!ctrl) { + switch(event->keyval) { + case GDK_h: + case GDK_H: + hidehp->set_active (!hidehp->get_active()); + return true; + case GDK_w: + case GDK_W: + tpc->getToolBar()->wb_pressed (); + return true; + case GDK_c: + case GDK_C: + tpc->getToolBar()->crop_pressed (); + return true; + case GDK_s: + case GDK_S: + tpc->getToolBar()->stra_pressed (); + return true; + case GDK_n: + case GDK_N: + tpc->getToolBar()->hand_pressed (); + return true; + case GDK_i: + case GDK_I: + info->set_active (!info->get_active()); + return true; + case GDK_b: + case GDK_B: + beforeAfter->set_active (!beforeAfter->get_active()); + return true; + case GDK_plus: + case GDK_equal: + iarea->imageArea->zoomPanel->zoomInClicked(); + return true; + case GDK_minus: + case GDK_underscore: + iarea->imageArea->zoomPanel->zoomOutClicked(); + return true; + case GDK_1: + iarea->imageArea->zoomPanel->zoom11Clicked(); + return true; + case GDK_f: + case GDK_F: + iarea->imageArea->zoomPanel->zoomFitClicked(); + return true; + } + } + else { + switch (event->keyval) { + case GDK_s: + saveAsPressed(); + return true; + case GDK_q: + queueImgPressed(); + return true; + case GDK_e: + sendToGimpPressed(); + return true; + case GDK_z: + history->undo (); + return true; + case GDK_Z: + history->redo (); + return true; + } + } + + return false; +} + +void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { + + if (whoChangedIt!=EDITOR) + tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, M("PROGRESSDLG_PROFILECHANGEDINBROWSER")); +} + +bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf, bool findNewNameIfNeeded){ + rtengine::IImage16* img = pc->returnValue(); + delete pc; + if( img ) + saveImage( img, fname, sf, findNewNameIfNeeded); + else{ + Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + + } + return false; +} + +BatchQueueEntry* EditorPanel::createBatchQueueEntry () { + + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + int prevh = options.maxThumbnailHeight; + int prevw = prevh; + guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh); + double tmpscale; + rtengine::IImage8* img = openThm->processThumbImage (pparams, options.maxThumbnailHeight, tmpscale); + if (img) { + prevw = img->getWidth (); + prevh = img->getHeight (); + prev = new guint8 [prevw*prevh*3]; + memcpy (prev, img->getData (), prevw*prevh*3); + img->free(); + } + return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm); +} + +int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) { + + Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + if (findNewNameIfNeeded) { + int tries = 1; + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { + fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); + tries++; + } + if (tries==1000) + return -1000; + } + ProgressConnector *ld = new ProgressConnector(); + img->setSaveProgressListener (parent->getProgressListener()); + if (sf.format=="tif") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + else if (sf.format=="png") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + else if (sf.format=="jpg") + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fileName,sf)); + return 0; +} + +bool EditorPanel::idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf){ + img->free (); + if (! pc->returnValue() ) { + openThm->imageDeveloped (); + // save processing parameters, if needed + if (sf.saveParams) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + pparams.save (removeExtension (fname) + ".out" + paramFileExtension); + } + }else{ + Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image saving\n"; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + } + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + parent->setProgressStr(""); + parent->setProgress(0.); + delete pc; + return false; +} + +void EditorPanel::saveAsPressed () { + + // obtaining short name without extension + saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName()))); + saveAsDialog->run (); + Glib::ustring fname = saveAsDialog->getFileName (); + if (fname=="") + return; + + options.lastSaveAsPath = saveAsDialog->getDirectory (); + options.saveAsDialogWidth = saveAsDialog->get_width(); + options.saveAsDialogHeight = saveAsDialog->get_height(); + + SaveFormat sf = saveAsDialog->getFormat (); + if (getExtension (fname)!=sf.format) + fname = fname + "." + sf.format; + + options.saveFormat = sf; + + if (saveAsDialog->getImmediately ()) { + // check if it exists + if (Glib::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 (); + if (response==Gtk::RESPONSE_NO) + return; + } + // save image + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + fname = removeExtension (fname); + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), + sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fname,sf,false )); + saveimgas->set_sensitive(false); + sendtogimp->set_sensitive(false); + } + else { + BatchQueueEntry* bqe = createBatchQueueEntry (); + bqe->outFileName = fname; + bqe->saveFormat = saveAsDialog->getFormat (); + parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); + } + // ask parent to redraw file browser + // ... or does it automatically when the tab is switched to it +} + +void EditorPanel::queueImgPressed () { + + saveProfile (); + parent->addBatchQueueJob (createBatchQueueEntry ()); +} + +void EditorPanel::sendToGimpPressed () { + // develop image + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener() ), + sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_sendToGimp ),ld )); + saveimgas->set_sensitive(false); + sendtogimp->set_sensitive(false); +} + +bool EditorPanel::idle_sendToGimp( ProgressConnector *pc){ + + rtengine::IImage16* img = pc->returnValue(); + delete pc; + if (img) { + // get file name base + Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName())); + Glib::ustring dirname = Glib::get_tmp_dir (); + Glib::ustring fname = Glib::build_filename (dirname, shortname); + + SaveFormat sf; + sf.format = "tif"; + sf.tiffBits = 16; + + Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + + int tries = 1; + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) { + fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); + tries++; + } + if (tries==1000){ + img->free (); + return false; + } + + ProgressConnector *ld = new ProgressConnector(); + img->setSaveProgressListener (parent->getProgressListener()); + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), + sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_sentToGimp), ld, img, fileName)); + }else{ + Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + } + return false; +} + +bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename){ + img->free (); + int errore = pc->returnValue(); + delete pc; + if (!errore) { + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + parent->setProgressStr(""); + parent->setProgress(0.); + bool success=false; + Glib::ustring cmdLine; + // start gimp + if (options.editorToSendTo==1) { +#ifdef _WIN32 + cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\""; +#else + cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + if (!success){ +#ifdef _WIN32 + int ver = 12; + while (!success && ver) { + cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\""; + ver--; + success = safe_spawn_command_line_async (cmdLine); + } +#elif defined __APPLE__ + cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; + success = safe_spawn_command_line_async (cmdLine); +#else + cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\""; + success = safe_spawn_command_line_async (cmdLine); +#endif + } + } + else if (options.editorToSendTo==2) { +#ifdef __APPLE__ + cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir,"Photoshop.app\' ") + "\'" + filename + "\'"; +#else + cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + } + else if (options.editorToSendTo==3) { +#ifdef __APPLE__ + cmdLine = Glib::ustring("") + options.customEditorProg + filename; +#else + cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\""; +#endif + success = safe_spawn_command_line_async (cmdLine); + } + + if (!success) { + Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); + msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR")); + msgd->run (); + delete msgd; + } + + } + + return false; +} + +void EditorPanel::saveOptions () { + + close(); + options.historyPanelWidth = hpanedl->get_position (); + options.toolPanelWidth = vboxright->get_width (); + if (options.startupDir==STARTUPDIR_LAST && fCatalog->lastSelectedDir ()!="") + options.startupPath = fCatalog->lastSelectedDir (); + fCatalog->closeDir (); +} + +void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { + + if (beforeIpc) { + ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged); + *pparams = params; + beforeIpc->paramsUpdateReady (); + } +} + +void EditorPanel::beforeAfterToggled () { + + removeIfThere (beforeAfterBox, beforeBox, false); + removeIfThere (afterBox, afterLabel, false); + + if (beforeIarea) { + if (beforeIpc) + beforeIpc->stopProcessing (); + iarea->setBeforeAfterViews (NULL, iarea); + delete beforeIarea; + beforeIarea = NULL; + if (beforeIpc) + beforeIpc->setPreviewImageListener (NULL); + delete beforePreviewHandler; + beforePreviewHandler = NULL; + if (beforeIpc) + rtengine::StagedImageProcessor::destroy (beforeIpc); + beforeIpc = NULL; + } + + if (beforeAfter->get_active ()) { + + beforeIarea = new ImageAreaPanel (); + + beforeLabel = Gtk::manage (new Gtk::Label ()); + beforeLabel->set_markup (Glib::ustring("") + M("GENERAL_BEFORE") + ""); + beforeBox = Gtk::manage (new Gtk::VBox ()); + beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2); + beforeBox->pack_start (*beforeIarea); + + afterLabel = Gtk::manage (new Gtk::Label ()); + afterLabel->set_markup (Glib::ustring("") + M("GENERAL_AFTER") + ""); + afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2); + afterBox->reorder_child (*afterLabel, 0); + + beforeAfterBox->pack_start (*beforeBox); + beforeAfterBox->reorder_child (*beforeBox, 0); + beforeAfterBox->show_all (); + + beforePreviewHandler = new PreviewHandler (); + isrc->increaseRef (); + beforeIpc = rtengine::StagedImageProcessor::create (isrc); + beforeIpc->setPreviewScale (10); + beforeIpc->setPreviewImageListener (beforePreviewHandler); + beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler); + beforeIarea->imageArea->setImProcCoordinator (beforeIpc); + + iarea->setBeforeAfterViews (beforeIarea, iarea); + beforeIarea->setBeforeAfterViews (beforeIarea, iarea); + + rtengine::procparams::ProcParams params; + if (history->getBeforeLineParams (params)) + historyBeforeLineChanged (params); + } +} + +void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) { + + histogramPanel->histogramChanged (rh, gh, bh, lh); + tpc->updateCurveBackgroundHistogram (bcrgb, bcl); +} diff --git a/rtgui/options.cc b/rtgui/options.cc index 72be1277f..88164e918 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -90,6 +90,7 @@ void Options::setDefaults () { maxCacheEntries = 10000; thumbnailFormat = FT_Custom16; thumbInterp = 1; + autoSuffix = false; saveParamsFile = false; saveParamsCache = true; paramsLoadLocation = PLL_Cache; @@ -198,6 +199,7 @@ if (keyFile.has_group ("Output")) { if (keyFile.has_key ("Output", "Path")) savePathTemplate = keyFile.get_string ("Output", "Path"); 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", "UsePathTemplate")) saveUsePathTemplate = keyFile.get_boolean("Output", "UsePathTemplate"); if (keyFile.has_key ("Output", "LastSaveAsPath")) lastSaveAsPath = keyFile.get_string ("Output", "LastSaveAsPath"); } @@ -357,6 +359,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_boolean ("Output", "SaveProcParams", saveFormat.saveParams); keyFile.set_string ("Output", "PathTemplate", savePathTemplate); keyFile.set_string ("Output", "PathFolder", savePathFolder); + keyFile.set_boolean("Output", "AutoSuffix", autoSuffix); keyFile.set_boolean("Output", "UsePathTemplate", saveUsePathTemplate); keyFile.set_string ("Output", "LastSaveAsPath", lastSaveAsPath); diff --git a/rtgui/options.h b/rtgui/options.h index e7d05e78c..75ff029fb 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -95,6 +95,7 @@ class Options { Glib::ustring language; Glib::ustring theme; static Glib::ustring cacheBaseDir; + bool autoSuffix; bool saveParamsFile; bool saveParamsCache; PPLoadLocation paramsLoadLocation; diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index e190128d8..f3baa9c4d 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -1,219 +1,215 @@ -/* - * 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 -#include -#include - -PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL),cCropMoving(NULL),cNormal(NULL), isMoving(false) { - - rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); -} - -PreviewWindow::~PreviewWindow () { - - if( cCropMoving ) - delete cCropMoving; - if( cNormal ) - delete cNormal; - -} - -void PreviewWindow::on_realize () { - - Gtk::DrawingArea::on_realize (); - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); - cCropMoving = new Gdk::Cursor (Gdk::FLEUR); -#ifdef _WIN32 - cNormal = new Gdk::Cursor (Gdk::ARROW); -#else - cNormal = new Gdk::Cursor (Gdk::ARROW); -#endif -} - -void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { - - if (mainCropWin) { - int cropX, cropY, cropW, cropH; - mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); - // translate it to screen coordinates - x = imgX + cropX*zoom; - y = imgY + cropY*zoom; - w = cropW * zoom; - h = cropH * zoom; - } -} - -void PreviewWindow::updatePreviewImage () { - - int W = get_width(), H = get_height(); - Glib::RefPtr wind = get_window(); - if( ! wind ) - return; - backBuffer = Gdk::Pixmap::create (wind, W, H, -1); - backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); - if (previewHandler) { - Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); - if (resPixbuf) { - imgW = resPixbuf->get_width(); - imgH = resPixbuf->get_height(); - imgX = (W-imgW)/2; - imgY = (H-imgH)/2; - backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); - Cairo::RefPtr cr = backBuffer->create_cairo_context(); - if (previewHandler->getCropParams().enabled) - drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams()); - } - } -} - -void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { - - previewHandler = ph; - if (previewHandler) - previewHandler->addPreviewImageListener (this); -} - -void PreviewWindow::on_resized (Gtk::Allocation& req) { - - updatePreviewImage (); - queue_draw (); -} - -bool PreviewWindow::on_expose_event (GdkEventExpose* event) { - - if (backBuffer) { - Glib::RefPtr window = get_window(); - - int bufferW, bufferH; - backBuffer->get_size (bufferW, bufferH); - - if (!mainCropWin) { - mainCropWin = imageArea->getMainCropWindow (); - if (mainCropWin) - mainCropWin->addCropWindowListener (this); - } - - if (get_width()!=bufferW && get_height()!=bufferH) - updatePreviewImage (); - - window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); - - if (mainCropWin) { - Cairo::RefPtr cr = get_window()->create_cairo_context(); - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - cr->set_source_rgb (1.0, 1.0, 1.0); - cr->set_line_width (3); - cr->rectangle (x-1.5, y-1.5, w+2, h+2); - cr->stroke (); - cr->set_source_rgb (1.0, 0.0, 0.0); - cr->set_line_width (1); - cr->rectangle (x-1.5, y-1.5, w+2, h+2); - cr->stroke (); - } - } - return true; -} - -void PreviewWindow::previewImageChanged () { - - updatePreviewImage (); - queue_draw (); -} - -void PreviewWindow::setImageArea (ImageArea* ia) { - - imageArea = ia; - mainCropWin = ia->getMainCropWindow (); - if (mainCropWin) - mainCropWin->addCropWindowListener (this); -} - -void PreviewWindow::cropPositionChanged (CropWindow* w) { - - queue_draw (); -} - -void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { - - queue_draw (); -} - -void PreviewWindow::cropZoomChanged (CropWindow* w) { - - queue_draw (); -} - -bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { - - if (!mainCropWin) - return true; - - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; - - if (isMoving) - mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); - else if (inside && !moreInside) - get_window()->set_cursor (*cCropMoving); - else - get_window()->set_cursor (*cNormal); - return true; -} - -bool PreviewWindow::on_button_press_event (GdkEventButton* event) { - - if (!mainCropWin) - return true; - - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; - - if (!isMoving) { - isMoving = true; - if (!inside || moreInside) { - mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); - press_x = x+w/2; - press_y = y+h/2; - } - else { - press_x = event->x; - press_y = event->y; - } - get_window()->set_cursor (*cCropMoving); - } - return true; -} - -bool PreviewWindow::on_button_release_event (GdkEventButton* event) { - - if (!mainCropWin) - return true; - - if (isMoving) { - isMoving = false; - get_window()->set_cursor (*cNormal); - mainCropWin->remoteMoveReady (); - } - return true; -} +/* + * 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 +#include +#include + +PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL),cCropMoving(NULL),cNormal(NULL), isMoving(false) { + + rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); +} + +PreviewWindow::~PreviewWindow () { + + if( cCropMoving ) + delete cCropMoving; + if( cNormal ) + delete cNormal; + +} + +void PreviewWindow::on_realize () { + + Gtk::DrawingArea::on_realize (); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + cCropMoving = new Gdk::Cursor (Gdk::FLEUR); + cNormal = new Gdk::Cursor (Gdk::ARROW); +} + +void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { + + if (mainCropWin) { + int cropX, cropY, cropW, cropH; + mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); + // translate it to screen coordinates + x = imgX + cropX*zoom; + y = imgY + cropY*zoom; + w = cropW * zoom; + h = cropH * zoom; + } +} + +void PreviewWindow::updatePreviewImage () { + + int W = get_width(), H = get_height(); + Glib::RefPtr wind = get_window(); + if( ! wind ) + return; + backBuffer = Gdk::Pixmap::create (wind, W, H, -1); + backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); + if (previewHandler) { + Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); + if (resPixbuf) { + imgW = resPixbuf->get_width(); + imgH = resPixbuf->get_height(); + imgX = (W-imgW)/2; + imgY = (H-imgH)/2; + backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + Cairo::RefPtr cr = backBuffer->create_cairo_context(); + if (previewHandler->getCropParams().enabled) + drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams()); + } + } +} + +void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { + + previewHandler = ph; + if (previewHandler) + previewHandler->addPreviewImageListener (this); +} + +void PreviewWindow::on_resized (Gtk::Allocation& req) { + + updatePreviewImage (); + queue_draw (); +} + +bool PreviewWindow::on_expose_event (GdkEventExpose* event) { + + if (backBuffer) { + Glib::RefPtr window = get_window(); + + int bufferW, bufferH; + backBuffer->get_size (bufferW, bufferH); + + if (!mainCropWin) { + mainCropWin = imageArea->getMainCropWindow (); + if (mainCropWin) + mainCropWin->addCropWindowListener (this); + } + + if (get_width()!=bufferW && get_height()!=bufferH) + updatePreviewImage (); + + window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); + + if (mainCropWin) { + Cairo::RefPtr cr = get_window()->create_cairo_context(); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + cr->set_source_rgb (1.0, 1.0, 1.0); + cr->set_line_width (3); + cr->rectangle (x-1.5, y-1.5, w+2, h+2); + cr->stroke (); + cr->set_source_rgb (1.0, 0.0, 0.0); + cr->set_line_width (1); + cr->rectangle (x-1.5, y-1.5, w+2, h+2); + cr->stroke (); + } + } + return true; +} + +void PreviewWindow::previewImageChanged () { + + updatePreviewImage (); + queue_draw (); +} + +void PreviewWindow::setImageArea (ImageArea* ia) { + + imageArea = ia; + mainCropWin = ia->getMainCropWindow (); + if (mainCropWin) + mainCropWin->addCropWindowListener (this); +} + +void PreviewWindow::cropPositionChanged (CropWindow* w) { + + queue_draw (); +} + +void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { + + queue_draw (); +} + +void PreviewWindow::cropZoomChanged (CropWindow* w) { + + queue_draw (); +} + +bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { + + if (!mainCropWin) + return true; + + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; + bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + + if (isMoving) + mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); + else if (inside && !moreInside) + get_window()->set_cursor (*cCropMoving); + else + get_window()->set_cursor (*cNormal); + return true; +} + +bool PreviewWindow::on_button_press_event (GdkEventButton* event) { + + if (!mainCropWin) + return true; + + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; + bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + + if (!isMoving) { + isMoving = true; + if (!inside || moreInside) { + mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); + press_x = x+w/2; + press_y = y+h/2; + } + else { + press_x = event->x; + press_y = event->y; + } + get_window()->set_cursor (*cCropMoving); + } + return true; +} + +bool PreviewWindow::on_button_release_event (GdkEventButton* event) { + + if (!mainCropWin) + return true; + + if (isMoving) { + isMoving = false; + get_window()->set_cursor (*cNormal); + mainCropWin->remoteMoveReady (); + } + return true; +} diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index 021a54207..d985100cf 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -22,6 +22,8 @@ extern Options options; SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { + set_title(M("GENERAL_SAVE")); + Gtk::VBox* vbox = get_vbox (); fchooser = new Gtk::FileChooserWidget (Gtk::FILE_CHOOSER_ACTION_SAVE); @@ -41,6 +43,16 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { Gtk::HSeparator* hsep1 = new Gtk::HSeparator (); vbox->pack_start (*hsep1, Gtk::PACK_SHRINK, 2); +// Unique filename option +// ~~~~~~~~~~~~~~~~~~~~~~ + autoSuffix = new Gtk::CheckButton (M("SAVEDLG_AUTOSUFFIX")); + autoSuffix->set_active(options.autoSuffix); + + vbox->pack_start (*autoSuffix, Gtk::PACK_SHRINK, 4); + + Gtk::HSeparator* hsep2 = new Gtk::HSeparator (); + vbox->pack_start (*hsep2, Gtk::PACK_SHRINK, 2); + // Output Options // ~~~~~~~~~~~~~~ formatOpts = new SaveFormatPanel (); @@ -49,8 +61,8 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { vbox->pack_start (*formatOpts, Gtk::PACK_SHRINK, 4); - Gtk::HSeparator* hsep2 = new Gtk::HSeparator (); - vbox->pack_start (*hsep2, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator* hsep3 = new Gtk::HSeparator (); + vbox->pack_start (*hsep3, Gtk::PACK_SHRINK, 2); // queue/immediate // ~~~~~~~~~~~~~ @@ -83,6 +95,11 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { show_all_children (); } +bool SaveAsDialog::getAutoSuffix () { + + return autoSuffix->get_active(); +} + bool SaveAsDialog::getImmediately () { return immediately->get_active (); diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 7df8d8392..1914461c4 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -28,6 +28,7 @@ class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { protected: Gtk::FileChooserWidget* fchooser; + Gtk::CheckButton* autoSuffix; SaveFormatPanel* formatOpts; Glib::ustring fname; Gtk::FileFilter filter_jpg; @@ -43,6 +44,7 @@ class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { Glib::ustring getFileName (); Glib::ustring getDirectory (); SaveFormat getFormat (); + bool getAutoSuffix (); bool getImmediately (); bool getToHeadOfQueue (); bool getToTailOfQueue (); diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index a7aab6efc..861d4a12c 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -401,7 +401,7 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { dirty = false; - Glib::RefPtr window = get_window(); + Glib::RefPtr window = get_window(); int w = get_width(); int h = get_height(); @@ -411,14 +411,14 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { Glib::RefPtr context = get_pango_context (); context->set_font_description (get_style()->get_font()); for (int i=0; ifd.size(); i++) { - if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) + if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) parent->fd[i]->updatepriority = false; else { parent->fd[i]->updatepriority = true; parent->fd[i]->draw (); } } - + return true; } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 8e9039d31..e94f2605b 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -344,8 +344,8 @@ void ThumbBrowserEntryBase::draw () { Glib::RefPtr gc_ = Gdk::GC::create (w->get_window()); - Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); - Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); + // Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); + // Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); Gdk::Color bgn = w->get_style()->get_bg(Gtk::STATE_NORMAL); Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED);